0

How can I link the transaction to the member, like link a transaction id to many member ids?

I have an activity to create new transaction, in that activity I enter the name of the transaction and have a button to insert. After I click on that button, I want to see the list of members.

Then I want to choose the members I want to link to the transaction. By clicking on every member, it should show me a tick or something next to the member I chose or it should set the clicked members in a different colour.

Then the transaction should be inserted with all the linked members I chose.

I did it like this for now, that I just make a new transaction, click on it, start a new activity with the chosen transaction, then in the toolbar I click on a button to start another activity where I should be able to choose the members I want to link with the transaction.

Is it possible to choose the members I want to link to the transaction directly with the new transaction activity? Or is it possible to make a new transaction and when I click on the button to save the new transaction, it inserts the record into the database and directly after insert, the activity where I choose the members to link to the transaction starts?

Also regarding my delete method: I have the method implemented in a onSwipe method. How can I do so that I can click on multiple transactions, they have a tick or a different colour, and delete them all at the same time?

I can click on a button (e.g. in the toolbar) to delete, then choose multiple members, click on a "confirm delete" button, let a confirmation screen appear (but not deleting yet), and after accepting the confirmation screen, delete them?

Class Transaction:

@Entity(tableName = "transaction_table")
public class Transaction {

@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "TransactionID")
private long id;

@ColumnInfo(name = "Transaction Name")
private String transactionName;

@ColumnInfo(name = "Transaction Balance")
private double balance;

public double getBalance() {
    return balance;
}

public void setBalance(double balance) {
    this.balance = balance;
}

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public String getTransactionName() {
    return transactionName;
}

public void setTransactionName(String transactionName) {
    this.transactionName = transactionName;
}

public Transaction(String transactionName, double balance) {
    this.transactionName = transactionName;
    this.balance = balance;
}

}

Class Member:

@Entity(tableName = "member_table")
public class Member {


@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "MemberID")
private long id;

@ColumnInfo(name = "First Name")
private String firstname;

@ColumnInfo(name = "Surname")
private String surname;

@ColumnInfo(name = "Balance")
private double balance;

public String getFirstname() {
    return firstname;
}

public void setFirstname(String firstname) {
    this.firstname = firstname;
}

public String getSurname() {
    return surname;
}

public void setSurname(String surname) {
    this.surname = surname;
}

public double getBalance() {
    return balance;
}

public void setBalance(double balance) {
    this.balance = balance;
}

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public Member(String firstname, String surname) {
    this.firstname = firstname;
    this.surname = surname;
    this.balance = 0;
}

}

Class Transaction Main Activity:

public class TransactionMainActivity extends AppCompatActivity implements TransactionListAdapter.TransactionClickListener {

private TransactionViewModel mTransactionViewModel;
private List<Transaction> mTransaction;

public static final int NEW_TRANSACTION_ACTIVITY_REQUEST_CODE = 1;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.transaction_activity);
    Toolbar toolbar = findViewById(R.id.toolbar_TransactionMainActivity);
    setSupportActionBar(toolbar);
    if (getSupportActionBar() != null) {
        getSupportActionBar().setTitle(R.string.Transaction);
    }

    FloatingActionButton fab = findViewById(R.id.fab_TransactionMainActivity);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(TransactionMainActivity.this, NewTransactionActivity.class);
            startActivityForResult(intent, NEW_TRANSACTION_ACTIVITY_REQUEST_CODE);
        }
    });

    RecyclerView recyclerView = findViewById(R.id.RecyclerViewCard_Transaction);
    final TransactionListAdapter adapter = new TransactionListAdapter(this);
    recyclerView.setAdapter(adapter);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    mTransactionViewModel = ViewModelProviders.of(this).get(TransactionViewModel.class);

    mTransactionViewModel.getAllTransactions().observe(this, new Observer<List<Transaction>>() {
        @Override
        public void onChanged(@Nullable List<Transaction> transactions) {
            mTransaction = transactions;
            adapter.setTransaction(transactions);
        }
    });

    ItemTouchHelper helper = new ItemTouchHelper(
            new ItemTouchHelper.SimpleCallback(0,
                    ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
                @Override
                public boolean onMove(RecyclerView recyclerView,
                                      RecyclerView.ViewHolder viewHolder,
                                      RecyclerView.ViewHolder target) {
                    return false;
                }

                @Override
                public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                    int position = viewHolder.getAdapterPosition();
                    Transaction myTransaction = adapter.getTransactionAtPosition(position);
                    Toast.makeText(TransactionMainActivity.this,
                            getString(R.string.TransactionDeleted) + " " +
                                    myTransaction.getTransactionName(), Toast.LENGTH_LONG).show();

                    mTransactionViewModel.delete(myTransaction);
                }
            });
    helper.attachToRecyclerView(recyclerView);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.MainMenuToolbarSearch:

        case R.id.MainMenuToolbarAdd:

        case R.id.MainMenuToolbarDelete:

    }
    return super.onOptionsItemSelected(item);
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == NEW_TRANSACTION_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
        Transaction transaction = new Transaction(data.getStringExtra(NewTransactionActivity.EXTRA_REPLY), data.getDoubleExtra(NewTransactionActivity.EXTRA_REPLY2, -1));
        mTransactionViewModel.insert(transaction);
    } else

    {
        Toast.makeText(
                getApplicationContext(),
                R.string.transaction_not_saved,
                Toast.LENGTH_LONG).show();
    }
}

Class New Transaction Activity:

public class NewTransactionActivity extends AppCompatActivity {

public static final String EXTRA_REPLY = "com.example.android.transactionlistsql.REPLY";
public static final String EXTRA_REPLY2 = "com.example.android.transactionlistsql.REPLY2";

private EditText mEditTextTransaction;
private EditText mEditTextTransaction2;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.newtransaction_activity);
    mEditTextTransaction = findViewById(R.id.NewTransactionName);
    mEditTextTransaction2 = findViewById(R.id.NewTransactionBalance);
    mEditTextTransaction2.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
    mEditTextTransaction2.setText("0");
    final Button button = findViewById(R.id.NewTransactionButtonSave);

    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent replyIntent = new Intent();
            if (TextUtils.isEmpty(mEditTextTransaction.getText())){
                Toast.makeText(getApplicationContext(), R.string.TransactionNameMissing, Toast.LENGTH_LONG).show();
                return;
            }
            else if (TextUtils.isEmpty(mEditTextTransaction2.getText())){
                mEditTextTransaction2.setText("0");
            }
            else {                 
                String newtransactionname = mEditTextTransaction.getText().toString();
                double newtransactionbalance = (Double.parseDouble(mEditTextTransaction2.getText().toString()));
                replyIntent.putExtra(EXTRA_REPLY, newtransactionname);
                replyIntent.putExtra(EXTRA_REPLY2, newtransactionbalance);
                setResult(RESULT_OK, replyIntent);
            }
            finish();
        }
    });
}
}

My AsyncTask for insert method:

    private static class insertAsyncTask extends AsyncTask<Transaction, Void, Void> {

    private TransactionDao mAsyncTaskDao;

    insertAsyncTask(TransactionDao dao) {
        mAsyncTaskDao = dao;
    }

    @Override
    protected Void doInBackground(final Transaction... params) {
        mAsyncTaskDao.insert(params[0]);
        return null;
    }
}

The line marked as error is this one: mAsyncTaskDao.insert(params[0]);

Error:

07-11 03:10:49.003 16307-16508/com.example.mainbuchhaltung E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #4

Process: com.example.mainbuchhaltung, PID: 16307

java.lang.RuntimeException: An error occurred while executing doInBackground()

    at android.os.AsyncTask$3.done(AsyncTask.java:309)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
    at java.lang.Thread.run(Thread.java:818)
 Caused by: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787)
#################################################################
Error Code : 787 (SQLITE_CONSTRAINT_FOEIGNKEY)
Caused By : Abort due to constraint violation.
    (FOREIGN KEY constraint failed (code 787))
#################################################################
    at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
    at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:915)
    at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
    at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
    at android.arch.persistence.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:50)
    at android.arch.persistence.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:64)
    at com.example.mainbuchhaltung.Transaction.TransactionDao_Impl.insert(TransactionDao_Impl.java:96)
    at com.example.mainbuchhaltung.Transaction.TransactionRepository$insertAsyncTask.doInBackground(TransactionRepository.java:64)
    at com.example.mainbuchhaltung.Transaction.TransactionRepository$insertAsyncTask.doInBackground(TransactionRepository.java:54)
    at android.os.AsyncTask$2.call(AsyncTask.java:295)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        ... 4 more
LordGash
  • 285
  • 1
  • 4
  • 14

1 Answers1

0

Create a relation between Transaction and Member entity like mentioned here

Then once you get transaction data (TransactionName and Amount) then you have to pass data to MemberList activity like here

Now in your MemberList screen once have done with your selection follow below process:
Suppose you have member ids in a string.

String memberIds = "12,18,25,27,30";

Now you have to create Transaction entity object with all member ids separated and insert it in the table of Transaction like below.

    String[] memberArray = memberIds.split(",", memberIds.length());
            for(String memberId : memberArray){
                // transactionName & transactionAmount which you received in the bundle from add transaction activity
                Transaction objTransaction = new Transaction(transactionName, transactionAmount); 
                objTransaction.setMemberId(Long.parseLong(memberId));
                // Insert data into your database
                mTransactionViewModel.insert(objTransaction);
            }

It will create a separate entry for each memberId in "transaction_table" table with one to one relationship.

You can fetch data of Transaction by executing query mentioned here

Viraj Patel
  • 2,113
  • 16
  • 23
  • Thank you so much for your help. One of the problems I face is that I don't have something implemented, which does the multiple selection. I only found examples of ListView Multiple Selection, but not for a RecyclerView. I also can't use the objTransaction.setMemberId, because it asks for a Long. Also, how can I do a many-to-many relationship? – LordGash Jul 09 '18 at 23:07
  • I'm sorry if I bother you with my questions, I began with programming not a long time ago, so I don't have enough programming experiences yet. – LordGash Jul 09 '18 at 23:12
  • @LordGash Check multiple item selection example of RecyclerView [here](https://stackoverflow.com/questions/36369913/how-to-implement-multi-select-in-recyclerview). I updated my answer to parse String to Long. You have to write `objTransaction.setMemberId(Long.parseLong(memberId));`. If you get member id in int then no need to Parse you can directly set it. – Viraj Patel Jul 10 '18 at 09:59
  • Thanks for all your help. I tried to do all the things. I implemented the multiple selection. But I don't know if the method to pass the members works, because after I added the ForeignKey, it shows me an error with the insert.AsyncTask method. I edit my post and put the error in it. Can you please help me with this one? – LordGash Jul 11 '18 at 01:09
  • @LordGash First of all, make sure you have MemberId exist in your member_table. If you try to insert member id into transaction_table which does not exist in member_table then it will give this type of error. [Read here for more info](https://www.sqlite.org/foreignkeys.html). Whenever you made any changes in your database structure during implementation/development time, please uninstall existing app first then install a fresh one. – Viraj Patel Jul 11 '18 at 06:23
  • but member does exist in my Member.class. I put the code above. The error was shown in the AsyncTask insert line right? In my Dao, as my insert method, I have this: @Insert void insert(Transaction transactions);. This is before the foreign key implementation. Do I have to change this Dao insert method after foreign key implementation? If yes, how do I change it? – LordGash Jul 11 '18 at 09:56
  • You insert method is correct. Just make sure that before you call insert method, your memberId set in the Transaction object. If possible, can you please make a demo project of your issue and share a link of it? It will be easy and fast to solve your problem. – Viraj Patel Jul 11 '18 at 11:50
  • Yeah sure, where should I upload the project? – LordGash Jul 11 '18 at 12:02
  • You can upload it on https://github.com/ or you can upload it on your google drive and share the link of it. – Viraj Patel Jul 11 '18 at 12:08
  • Okay, wait a moment, gonna upload it to Google Drive. – LordGash Jul 11 '18 at 12:10
  • @LordGash the problem is in `mTransactionViewModel.insert(transaction);` in your `TransactionMainActivity.java` file. In your transaction object, MemberId is not set and you are trying to insert it into database therefore it is giving `FOREIGN KEY constraint failed` error. I resolved your error but one question is how you want to display data in Transaction list screen. [Check this screenshot.](https://imgur.com/a/Yr5LCBD) – Viraj Patel Jul 12 '18 at 07:03
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/174873/discussion-between-lordgash-and-viraj-patel). – LordGash Jul 12 '18 at 10:02