Hello I am new to android studios. I am working on an airline reservation project. One of the requirements of the project is to generate a receipt that is stored on an external file every time a customer makes a payment. I have tried looking around trying to figure out how one might accomplish this with no success. In the app I am using SQLite as a database where every user is assigned a balance once they create an account.
Here is my DBHelper class:
package com.example.shashank.fffffffffffffffffffffffffff;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
public class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "Login.db";
public static final String FLIGHTS = "FLIGHTS";
public static final String COLUMN_ID = "ID";
public static final String COLUMN_DESTINATION = "DESTINATION";
public static final String COLUMN_PRICE = "PRICE";
public static final String COLUMN_DEPARTURE_TIME = "DEPARTURE_TIME";
public static final String COLUMN_ARRIVAL_TIME = "ARRIVAL_TIME";
public static final String COLUMN_DURATION = "DURATION";
public static final String COLUMN_AVAILABLE_SEATS = "AVAILABLE_SEATS";
public static final String USERS = "users";
public static final String USERNAME = "username";
public static final String PASSWORD = "password";
public static final String EMAIL = "email";
public static final String BALANCE = "balance";
public static final String BOOKING = "booking";
public DBHelper(Context context) {
super(context, "Login.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase MyDB) {
String createTable1 = ("create Table " USERS "(" USERNAME " TEXT primary key, " PASSWORD " TEXT, " EMAIL " TEXT UNIQUE, " BALANCE " REAL, " BOOKING " INTEGER)");
MyDB.execSQL(createTable1);
MyDB.execSQL("CREATE TABLE " FLIGHTS "(" COLUMN_ID " INTEGER PRIMARY KEY AUTOINCREMENT, " COLUMN_DESTINATION " TEXT, " COLUMN_PRICE " REAL, " COLUMN_DEPARTURE_TIME " TEXT, " COLUMN_ARRIVAL_TIME " TEXT, " COLUMN_DURATION " TEXT, " COLUMN_AVAILABLE_SEATS " INTEGER)");
ContentValues insertValues = new ContentValues();
insertValues.put(COLUMN_DESTINATION, "Cape Town");
insertValues.put(COLUMN_PRICE, 2000);
insertValues.put(COLUMN_DEPARTURE_TIME, "1200");
insertValues.put(COLUMN_ARRIVAL_TIME, "1400");
insertValues.put(COLUMN_DURATION, "2");
insertValues.put(COLUMN_AVAILABLE_SEATS, 10);
MyDB.insert(FLIGHTS, null, insertValues);
ContentValues insertValues2 = new ContentValues();
insertValues2.put(COLUMN_DESTINATION, "Johannesburg");
insertValues2.put(COLUMN_PRICE, 1000);
insertValues2.put(COLUMN_DEPARTURE_TIME, "1400");
insertValues2.put(COLUMN_ARRIVAL_TIME, "1600");
insertValues2.put(COLUMN_DURATION, "2");
insertValues2.put(COLUMN_AVAILABLE_SEATS, 22);
MyDB.insert(FLIGHTS, null, insertValues2);
ContentValues insertValues3 = new ContentValues();
insertValues3.put(COLUMN_DESTINATION, "Cape Town");
insertValues3.put(COLUMN_PRICE, 500);
insertValues3.put(COLUMN_DEPARTURE_TIME, "1200");
insertValues3.put(COLUMN_ARRIVAL_TIME, "1400");
insertValues3.put(COLUMN_DURATION, "2");
insertValues3.put(COLUMN_AVAILABLE_SEATS, 0);
MyDB.insert(FLIGHTS, null, insertValues3);
}
@Override
public void onUpgrade(SQLiteDatabase MyDB, int i, int i1) {
MyDB.execSQL("drop Table if exists " USERS);
MyDB.execSQL("drop Table if exists " FLIGHTS);
onCreate(MyDB);
}
public Boolean insertData(String username, String password, String email, Double balance){
SQLiteDatabase MyDB = this.getWritableDatabase();
ContentValues contentValues= new ContentValues();
contentValues.put(USERNAME, username);
contentValues.put(PASSWORD, password);
contentValues.put(EMAIL, email);
contentValues.put(BALANCE, balance);
long result = MyDB.insert(USERS, null, contentValues);
if(result==-1) return false;
else
return true;
}
public Boolean checkusername(String username) {
SQLiteDatabase MyDB = this.getWritableDatabase();
Cursor cursor = MyDB.rawQuery("Select * from " USERS " where " USERNAME " = ?", new String[]{username});
if (cursor.getCount() > 0)
return true;
else
return false;
}
public Boolean checkusernamepassword(String username, String password){
SQLiteDatabase MyDB = this.getWritableDatabase();
Cursor cursor = MyDB.rawQuery("Select * from " USERS " where " USERNAME " = ? and " PASSWORD " = ?", new String[] {username,password});
if(cursor.getCount()>0)
return true;
else
return false;
}
public List<FlightsModel> getEveryone(){
List<FlightsModel> returnList = new ArrayList<>();
String queryString = "SELECT * FROM " FLIGHTS;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(queryString, null);
if(cursor.moveToFirst()){
do {
int id = cursor.getInt(0);
String destination = cursor.getString(1);
double price = cursor.getDouble(2);
String departure = cursor.getString(3);
String arrival = cursor.getString(4);
String duration = cursor.getString(5);
int space = cursor.getInt(6);
FlightsModel newFlight = new FlightsModel(id, destination, price, departure, arrival, duration, space);
returnList.add(newFlight);
}while (cursor.moveToNext());
}
else{
}
cursor.close();
db.close();
return returnList;
}
@SuppressLint("Range") // suppress Bug/issue with getColumnIndex
public FlightsModel getFlightById(int id) {
FlightsModel rv;
SQLiteDatabase db = this.getWritableDatabase();
// Uses the query convenience method rather than raw query
Cursor csr = db.query(FLIGHTS,null,COLUMN_ID "=?",new String[]{String.valueOf(id)},null,null,null);
if (csr.moveToFirst()) {
rv = new FlightsModel(
csr.getInt(csr.getColumnIndex(COLUMN_ID)),
csr.getString(csr.getColumnIndex(COLUMN_DESTINATION)),
csr.getDouble(csr.getColumnIndex(COLUMN_PRICE)),
csr.getString(csr.getColumnIndex(COLUMN_DEPARTURE_TIME)),
csr.getString(csr.getColumnIndex(COLUMN_ARRIVAL_TIME)),
csr.getString(csr.getColumnIndex(COLUMN_DURATION)),
csr.getInt(csr.getColumnIndex(COLUMN_AVAILABLE_SEATS))
);
} else {
rv = new FlightsModel();
}
csr.close();
// No need to close the database (inefficient to keep opening and closing db)
return rv;
}
@SuppressLint("Range")
public UsersModel getPasswordByName(String name){
UsersModel rv;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cr = db.query(USERS, null, USERNAME "=?", new String[]{name}, null, null, null);
if (cr.moveToFirst()) {
rv = new UsersModel(
cr.getString(cr.getColumnIndex(USERNAME)),
cr.getString(cr.getColumnIndex(PASSWORD)),
cr.getString(cr.getColumnIndex(EMAIL)),
cr.getDouble(cr.getColumnIndex(BALANCE)),
cr.getInt(cr.getColumnIndex(BOOKING))
);
} else rv = new UsersModel();
cr.close();
return rv;
}
public int setBookingByUserName(int bookingAmount, String userName) {
ContentValues cv = new ContentValues();
cv.put(BOOKING,bookingAmount);
return this.getWritableDatabase().update(USERS,cv,USERNAME "=?",new String[]{userName});
}
public double makingPayment(double balance, String userName){
ContentValues cv = new ContentValues();
cv.put(BALANCE,balance);
return this.getWritableDatabase().update(USERS,cv,USERNAME "=?",new String[]{userName});
}
public int setAvailableSeatsAfterPayment(int seats, int flightID){
ContentValues cv = new ContentValues();
cv.put(COLUMN_AVAILABLE_SEATS,seats);
return this.getWritableDatabase().update(FLIGHTS,cv,COLUMN_ID "=?",new String[]{String.valueOf(flightID)});
}
public int cancelBooking(int bookingAmount, String userName){
ContentValues cv = new ContentValues();
cv.put(BOOKING,bookingAmount);
return this.getWritableDatabase().update(USERS,cv,USERNAME "=?",new String[]{String.valueOf(userName)});
}
}
The making payment method is used to update the database with a new balance when a customer books for a flight.
Here is the booking activity:
package com.example.shashank.fffffffffffffffffffffffffff;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class BookingActivity extends AppCompatActivity {
TextView textView;
TextView departure, arrival, duration, price, seats;
DBHelper dbHelper; //<<<<< ADDED
Button book, accountBtn;
FlightsModel flightsModel; //<<<<< ADDED
UsersModel userModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_booking);
dbHelper = new DBHelper(this); //<<<<< ADDED
textView = findViewById(R.id.textView);
departure = findViewById(R.id.departure);
arrival = findViewById(R.id.arrival);
duration = findViewById(R.id.duration);
price = findViewById(R.id.price);
seats = findViewById(R.id.seats);
book = findViewById(R.id.button2);
accountBtn = findViewById(R.id.accountBtn);
Intent mIntent = getIntent();
int intValue = mIntent.getIntExtra("intVariableName", 0);
Intent nameIntent = getIntent();
String name = nameIntent.getStringExtra("userName");
flightsModel = dbHelper.getFlightById(intValue 1);
intValue = intValue 1;
textView.setText(flightsModel.getDestination());
departure.setText(flightsModel.getDeparture_time());
arrival.setText(flightsModel.getArrival_time());
duration.setText(flightsModel.getDuration());
price.setText("R" Double.toString(flightsModel.getPrice()));
seats.setText(Integer.toString(flightsModel.getAvailable_space()));
book.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int intValue, seats;
Intent mIntent = getIntent();
intValue = mIntent.getIntExtra("intVariableName", 0);
intValue = intValue 1;
dbHelper = new DBHelper(BookingActivity.this);
flightsModel = dbHelper.getFlightById(intValue);
double price;
price = flightsModel.getPrice();
userModel = dbHelper.getPasswordByName(name);
double balance;
balance = userModel.getBalance();
String name = nameIntent.getStringExtra("userName");
seats = flightsModel.getAvailable_space();
if(seats == 0){
Toast.makeText(BookingActivity.this, "Booking unsuccessful, no available seats", Toast.LENGTH_SHORT).show();
}else{
if(price <= balance){
dbHelper.setBookingByUserName(intValue, name);
Toast.makeText(BookingActivity.this, "Payment successful, booking has been made", Toast.LENGTH_SHORT).show();
double newBalance;
newBalance = balance - price;
dbHelper.makingPayment(newBalance, name);
seats = seats - 1;
dbHelper.setAvailableSeatsAfterPayment(seats, intValue);
}else{
Toast.makeText(BookingActivity.this, "Payment unsuccessful, not enough funds", Toast.LENGTH_SHORT).show();
}
}
}
});
accountBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(BookingActivity.this, AccountActivity.class);
intent.putExtra("userName", name);
startActivity(intent);
}
});
}
}
So once a customer makes his booking a receipt file needs to be generated, say for instance with the flight details, time, date and the price of the flight. Any help will be appreciated thank you.
CodePudding user response:
The following is an example that saves a file in the App's Files directory in a sub directory of receipts. The filename being composed of values e.g. Fred-Cape Town-1200-1400
Stored at /data/user/0/the_package_name/files/receipts/Fred-Cape Town-1200-1400
The file itself, in the example containing :-
Fred
Cape Town
1200
1400
Some supportive methods added to DBHelper :-
public UsersModel getUsersModelByName(String userName) {
UsersModel rv = new UsersModel();
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr = db.query(USERS,null,USERNAME "=?", new String[]{userName},null,null,null);
if (csr.moveToFirst()) {
rv = new UsersModel(
csr.getString(csr.getColumnIndex(USERNAME)),
csr.getString(csr.getColumnIndex(PASSWORD)),
csr.getString(csr.getColumnIndex(EMAIL)),
csr.getDouble(csr.getColumnIndex(BALANCE)),
csr.getInt(csr.getColumnIndex(BOOKING))
);
}
csr.close();
return rv;
}
public boolean makeBooking(String userName, int bookingId) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(BOOKING,bookingId);
return db.update(USERS,cv,USERNAME "=?", new String[]{userName}) > 0;
}
Now the makeBookReceiptFile method, also placed in the DBHelper class:-
public String makeBookReceiptFile(String userName, Context context) {
String rcpts_directory = "receipts";
String rv = "";
SQLiteDatabase db = this.getWritableDatabase();
UsersModel currentUser = getUsersModelByName(userName);
FlightsModel currentFlightsModel = new FlightsModel();
if (currentUser.booking > 0) {
currentFlightsModel = getFlightById(currentUser.booking);
if (currentFlightsModel.id < 1) {
rv = "INVALID - unable to extract booking for id " currentUser.booking;
}
} else {
rv = "INVALID - unable to extract user who's name is " userName;
}
if (rv.length() > 0) return rv;
String rcpt_filename =
currentUser.username "-"
currentFlightsModel.destination "-"
currentFlightsModel.departure "-"
currentFlightsModel.arrival
;
File rcpt = new File(context.getFilesDir().getPath() File.separatorChar rcpts_directory File.separatorChar rcpt_filename);
rcpt.getParentFile().mkdirs();
try {
FileWriter fw = new FileWriter(rcpt);
fw.write(userName
"\n" currentFlightsModel.destination
"\n" currentFlightsModel.departure
"\n" currentFlightsModel.arrival
);
fw.flush();
fw.close();
rv = rcpt.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
rv = "IOERROR - " e.getMessage();
}
return rv;
}
First it retrieves the UsersModel according to the UserName, the it retrieves the FlightsModel according to the booking id.
If either was not obtained then it returns a String starting with INVALID
It then obtains the Files directory via the Context. Generates the path for the file. Makes any missing directories. Write data to the file, flushes and closes the file returning the path or if there was an io error the error message.
The above was tested using :-
db = new DBHelper(this);
db.insertData("Fred","password","fed@email",0.00);
UsersModel fred = db.getUsersModelByName("Fred");
db.makeBooking(fred.username,1);
Log.d("RESULTINFO",db.makeBookReceiptFile("Fred",this));
Resulting in (via Device Explorer) :-
If you have issues with the location of the file then you will have to read https://developer.android.com/training/data-storage/