Skip to content
This repository was archived by the owner on Jun 27, 2020. It is now read-only.

Commit be09528

Browse files
author
Evgenii Kanivets
committed
#70[1h]. Validate 'Add record' screen.
1 parent 963ac70 commit be09528

File tree

6 files changed

+198
-75
lines changed

6 files changed

+198
-75
lines changed

app/src/main/java/com/blogspot/e_kanivets/moneytracker/activity/record/AddRecordActivity.java

Lines changed: 47 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import android.widget.EditText;
2626
import android.widget.TextView;
2727
import android.widget.TimePicker;
28+
import android.widget.Toast;
2829

2930
import com.blogspot.e_kanivets.moneytracker.R;
3031
import com.blogspot.e_kanivets.moneytracker.activity.base.BaseBackActivity;
@@ -34,9 +35,10 @@
3435
import com.blogspot.e_kanivets.moneytracker.controller.data.CategoryController;
3536
import com.blogspot.e_kanivets.moneytracker.controller.data.RecordController;
3637
import com.blogspot.e_kanivets.moneytracker.entity.data.Account;
37-
import com.blogspot.e_kanivets.moneytracker.entity.data.Category;
3838
import com.blogspot.e_kanivets.moneytracker.entity.data.Record;
3939
import com.blogspot.e_kanivets.moneytracker.util.CategoryAutoCompleter;
40+
import com.blogspot.e_kanivets.moneytracker.util.validator.IValidator;
41+
import com.blogspot.e_kanivets.moneytracker.util.validator.RecordValidator;
4042

4143
import java.util.ArrayList;
4244
import java.util.Calendar;
@@ -61,6 +63,7 @@ public class AddRecordActivity extends BaseBackActivity {
6163
public static final String KEY_MODE = "key_mode";
6264
public static final String KEY_TYPE = "key_type";
6365

66+
@Nullable
6467
private Record record;
6568
private Mode mode;
6669
private int type;
@@ -79,6 +82,10 @@ public class AddRecordActivity extends BaseBackActivity {
7982
@Inject
8083
FormatController formatController;
8184

85+
private IValidator<Record> recordValidator;
86+
87+
@Bind(R.id.content)
88+
View contentView;
8289
@Bind(R.id.tv_date)
8390
TextView tvDate;
8491
@Bind(R.id.tv_time)
@@ -107,10 +114,11 @@ record = getIntent().getParcelableExtra(KEY_RECORD);
107114
type = getIntent().getIntExtra(KEY_TYPE, -1);
108115
accountList = accountController.readAll();
109116

110-
if (mode == Mode.MODE_EDIT) timestamp = record.getTime();
117+
if (mode == Mode.MODE_EDIT && record != null) timestamp = record.getTime();
111118
else timestamp = new Date().getTime();
112119

113-
return mode != null && type != -1 && (!mode.equals(Mode.MODE_EDIT) || record != null);
120+
return mode != null && (type == Record.TYPE_INCOME || type == Record.TYPE_EXPENSE)
121+
&& (!mode.equals(Mode.MODE_EDIT) || record != null);
114122
}
115123

116124
@SuppressWarnings("deprecation")
@@ -119,6 +127,10 @@ record = getIntent().getParcelableExtra(KEY_RECORD);
119127
protected void initViews() {
120128
super.initViews();
121129

130+
long recordId = record == null ? -1 : record.getId();
131+
recordValidator = new RecordValidator(AddRecordActivity.this, contentView, mode,
132+
accountList, timestamp, type, recordId);
133+
122134
// Add texts to dialog if it's edit dialog
123135
if (mode == Mode.MODE_EDIT) {
124136
etTitle.setText(record.getTitle());
@@ -132,7 +144,8 @@ protected void initViews() {
132144
if (getSupportActionBar() != null) {
133145
switch (type) {
134146
case Record.TYPE_EXPENSE:
135-
if (mode == Mode.MODE_ADD) getSupportActionBar().setTitle(R.string.title_add_expense);
147+
if (mode == Mode.MODE_ADD)
148+
getSupportActionBar().setTitle(R.string.title_add_expense);
136149
else getSupportActionBar().setTitle(R.string.title_edit_expense);
137150
getSupportActionBar().setBackgroundDrawable(
138151
new ColorDrawable(getResources().getColor(R.color.red_light)));
@@ -145,7 +158,8 @@ protected void initViews() {
145158
break;
146159

147160
case Record.TYPE_INCOME:
148-
if (mode == Mode.MODE_ADD) getSupportActionBar().setTitle(R.string.title_add_income);
161+
if (mode == Mode.MODE_ADD)
162+
getSupportActionBar().setTitle(R.string.title_add_income);
149163
else getSupportActionBar().setTitle(R.string.title_edit_income);
150164
getSupportActionBar().setBackgroundDrawable(
151165
new ColorDrawable(getResources().getColor(R.color.green_light)));
@@ -217,9 +231,10 @@ public boolean onOptionsItemSelected(MenuItem item) {
217231
return true;
218232

219233
case R.id.action_delete:
220-
recordController.delete(record);
221-
setResult(RESULT_OK);
222-
finish();
234+
if (recordController.delete(record)) {
235+
setResult(RESULT_OK);
236+
finish();
237+
}
223238
return true;
224239

225240
default:
@@ -244,6 +259,8 @@ public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth
244259
if (calendar.getTimeInMillis() < new Date().getTime()) {
245260
timestamp = calendar.getTimeInMillis();
246261
updateDateAndTime();
262+
} else {
263+
showToast(R.string.record_in_future);
247264
}
248265
}
249266
}, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
@@ -267,20 +284,15 @@ public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
267284
if (calendar.getTimeInMillis() < new Date().getTime()) {
268285
timestamp = calendar.getTimeInMillis();
269286
updateDateAndTime();
287+
} else {
288+
showToast(R.string.record_in_future);
270289
}
271290
}
272291
}, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE),
273292
DateFormat.is24HourFormat(AddRecordActivity.this));
274293
dialog.show();
275294
}
276295

277-
private void tryRecord() {
278-
if (prepareRecord()) {
279-
setResult(RESULT_OK);
280-
finish();
281-
} else showToast(R.string.wrong_number_text);
282-
}
283-
284296
private void presentSpinnerAccount() {
285297
List<String> accounts = new ArrayList<>();
286298
for (Account account : accountList) {
@@ -290,7 +302,7 @@ private void presentSpinnerAccount() {
290302
int selectedAccountIndex = -1;
291303

292304
if (mode == Mode.MODE_EDIT) {
293-
if (record.getAccount() != null) {
305+
if (record != null && record.getAccount() != null) {
294306
for (int i = 0; i < accountList.size(); i++) {
295307
Account account = accountList.get(i);
296308
if (account.getId() == record.getAccount().getId()) selectedAccountIndex = i;
@@ -310,72 +322,36 @@ private void presentSpinnerAccount() {
310322
selectedAccountIndex = 0;
311323
spinnerAccount.setEnabled(false);
312324

313-
accounts = new ArrayList<>();
314-
accounts.add(getString(R.string.account_was_removed));
325+
if (accounts.size() == 0) {
326+
accounts.add(getString(R.string.none));
327+
} else {
328+
accounts.add(getString(R.string.account_was_removed));
329+
}
315330
}
316331

317332
spinnerAccount.setAdapter(new ArrayAdapter<>(AddRecordActivity.this,
318333
R.layout.view_spinner_item, accounts));
319334
spinnerAccount.setSelection(selectedAccountIndex);
320335
}
321336

322-
private boolean prepareRecord() {
323-
String title = etTitle.getText().toString().trim();
324-
String category = etCategory.getText().toString().trim();
325-
326-
if (title.isEmpty()) return false;
327-
if (category.isEmpty()) return false;
328-
329-
//Check if price is valid
330-
double price = -1;
331-
try {
332-
price = Double.parseDouble(etPrice.getText().toString());
333-
} catch (NumberFormatException e) {
334-
e.printStackTrace();
337+
private void tryRecord() {
338+
if (addRecord()) {
339+
setResult(RESULT_OK);
340+
finish();
335341
}
336-
337-
long now = new Date().getTime();
338-
if (timestamp > now) return false;
339-
340-
if (price < 0.0 || price > 1000000000.0) return false;
341-
342-
if (spinnerAccount.getSelectedItemPosition() < 0) return false;
343-
344-
Account account = null;
345-
if (spinnerAccount.isEnabled())
346-
account = accountList.get(spinnerAccount.getSelectedItemPosition());
347-
348-
return doRecord(timestamp, title, category, price, account);
349342
}
350343

351-
private boolean doRecord(long timestamp, String title, String category, double price,
352-
@Nullable Account account) {
353-
if (account == null) return false;
354-
355-
if (mode == Mode.MODE_ADD) {
356-
switch (type) {
357-
case Record.TYPE_EXPENSE:
358-
recordController.create(new Record(timestamp, Record.TYPE_EXPENSE, title,
359-
new Category(category), price, account, account.getCurrency()));
360-
return true;
361-
362-
case Record.TYPE_INCOME:
363-
recordController.create(new Record(timestamp, Record.TYPE_INCOME, title,
364-
new Category(category), price, account, account.getCurrency()));
365-
return true;
366-
367-
default:
368-
return false;
369-
}
370-
} else if (mode == Mode.MODE_EDIT) {
371-
Record updatedRecord = new Record(record.getId(), timestamp, record.getType(),
372-
title, new Category(category), price, account, account.getCurrency());
373-
recordController.update(updatedRecord);
374-
375-
return true;
344+
@SuppressWarnings("SimplifiableIfStatement")
345+
private boolean addRecord() {
346+
Record newRecord = recordValidator.validate();
347+
if (newRecord == null) return false;
348+
else {
349+
if (mode == Mode.MODE_ADD) {
350+
return recordController.create(newRecord) != null;
351+
} else if (mode == Mode.MODE_EDIT) {
352+
return recordController.update(newRecord) != null;
353+
} else return false;
376354
}
377-
378-
return false;
379355
}
380356

381357
private void updateDateAndTime() {

app/src/main/java/com/blogspot/e_kanivets/moneytracker/util/validator/AccountValidator.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import android.support.annotation.Nullable;
66
import android.support.design.widget.TextInputLayout;
77
import android.support.v7.widget.AppCompatSpinner;
8-
import android.text.Editable;
9-
import android.text.TextWatcher;
108
import android.view.View;
119
import android.widget.EditText;
1210

@@ -72,7 +70,7 @@ public Account validate() {
7270
}
7371

7472
if (Math.abs(initSum) > MAX_ABS_VALUE) {
75-
tilInitSum.setError(context.getString(R.string.too_rich));
73+
tilInitSum.setError(context.getString(R.string.too_rich_or_poor));
7674
valid = false;
7775
}
7876

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package com.blogspot.e_kanivets.moneytracker.util.validator;
2+
3+
import android.content.Context;
4+
import android.support.annotation.NonNull;
5+
import android.support.annotation.Nullable;
6+
import android.support.design.widget.TextInputLayout;
7+
import android.support.v7.widget.AppCompatSpinner;
8+
import android.view.View;
9+
import android.widget.EditText;
10+
import android.widget.Toast;
11+
12+
import com.blogspot.e_kanivets.moneytracker.R;
13+
import com.blogspot.e_kanivets.moneytracker.activity.record.AddRecordActivity;
14+
import com.blogspot.e_kanivets.moneytracker.entity.data.Account;
15+
import com.blogspot.e_kanivets.moneytracker.entity.data.Category;
16+
import com.blogspot.e_kanivets.moneytracker.entity.data.Record;
17+
18+
import java.util.Date;
19+
import java.util.List;
20+
21+
import butterknife.Bind;
22+
import butterknife.ButterKnife;
23+
24+
/**
25+
* Util class for Account validation.
26+
* Created on 06.12.2016.
27+
*
28+
* @author Evgenii Kanivets
29+
*/
30+
31+
public class RecordValidator implements IValidator<Record> {
32+
33+
@NonNull
34+
private final Context context;
35+
36+
private AddRecordActivity.Mode mode;
37+
private List<Account> accountList;
38+
private long timestamp;
39+
private long recordId;
40+
private int recordType;
41+
42+
@Bind(R.id.til_title)
43+
TextInputLayout tilTitle;
44+
@Bind(R.id.et_title)
45+
EditText etTitle;
46+
@Bind(R.id.til_category)
47+
TextInputLayout tilCategory;
48+
@Bind(R.id.et_category)
49+
EditText etCategory;
50+
@Bind(R.id.til_price)
51+
TextInputLayout tilPrice;
52+
@Bind(R.id.et_price)
53+
EditText etPrice;
54+
@Bind(R.id.spinner_account)
55+
AppCompatSpinner spinnerAccount;
56+
57+
public RecordValidator(@NonNull Context context, @NonNull View view,
58+
@NonNull AddRecordActivity.Mode mode, @NonNull List<Account> accountList,
59+
long timestamp, int recordType, long recordId) {
60+
this.context = context;
61+
this.mode = mode;
62+
this.accountList = accountList;
63+
this.timestamp = timestamp;
64+
this.recordType = recordType;
65+
this.recordId = recordId;
66+
67+
ButterKnife.bind(this, view);
68+
initTextWatchers();
69+
}
70+
71+
@Nullable
72+
@Override
73+
public Record validate() {
74+
boolean valid = true;
75+
76+
String title = etTitle.getText().toString().trim();
77+
String category = etCategory.getText().toString().trim();
78+
79+
if (title.isEmpty()) {
80+
title = category;
81+
}
82+
83+
if (category.isEmpty()) {
84+
tilCategory.setError(context.getString(R.string.field_cant_be_empty));
85+
valid = false;
86+
}
87+
88+
//Check if price is valid
89+
double price = Double.MAX_VALUE;
90+
try {
91+
price = Double.parseDouble(etPrice.getText().toString());
92+
} catch (NumberFormatException e) {
93+
e.printStackTrace();
94+
}
95+
96+
if (price == Double.MAX_VALUE) {
97+
tilPrice.setError(context.getString(R.string.field_cant_be_empty));
98+
price = 0;
99+
valid = false;
100+
}
101+
102+
if (price > MAX_ABS_VALUE) {
103+
tilPrice.setError(context.getString(R.string.too_rich));
104+
valid = false;
105+
}
106+
107+
long now = new Date().getTime();
108+
if (timestamp > now) {
109+
Toast.makeText(context, R.string.record_in_future, Toast.LENGTH_SHORT).show();
110+
valid = false;
111+
}
112+
113+
Account account = null;
114+
if (spinnerAccount.isEnabled()) {
115+
account = accountList.get(spinnerAccount.getSelectedItemPosition());
116+
} else {
117+
Toast.makeText(context, R.string.one_account_needed, Toast.LENGTH_SHORT).show();
118+
valid = false;
119+
}
120+
121+
Record record = null;
122+
if (account != null) {
123+
if (mode == AddRecordActivity.Mode.MODE_ADD) {
124+
record = new Record(timestamp, recordType, title, new Category(category),
125+
price, account, account.getCurrency());
126+
} else if (mode == AddRecordActivity.Mode.MODE_EDIT) {
127+
record = new Record(recordId, timestamp, recordType, title, new Category(category),
128+
price, account, account.getCurrency());
129+
}
130+
}
131+
132+
return valid ? record : null;
133+
}
134+
135+
private void initTextWatchers() {
136+
etPrice.addTextChangedListener(new ClearErrorTextWatcher(tilPrice));
137+
etTitle.addTextChangedListener(new ClearErrorTextWatcher(tilTitle));
138+
etCategory.addTextChangedListener(new ClearErrorTextWatcher(tilCategory));
139+
}
140+
}

0 commit comments

Comments
 (0)