diff --git a/db/function/view_apt_amen_to_pay.sql b/db/function/view_apt_amen_to_pay.sql index 8d4b9ef..aeae323 100644 --- a/db/function/view_apt_amen_to_pay.sql +++ b/db/function/view_apt_amen_to_pay.sql @@ -6,7 +6,12 @@ CREATE OR REPLACE FUNCTION apt_amen_to_pay ( AS tbl_out amen_pay_table; BEGIN - SELECT amen_pay_row(amenity.id, amenity, cost) + SELECT amen_pay_row( + amenity.id, + amenity, + cost, + CEIL(MONTHS_BETWEEN(CURRENT_TIMESTAMP, date_paid)) + ) BULK COLLECT INTO tbl_out FROM -- Check amenities that correspond to the person's lease diff --git a/db/function/view_lease_to_pay.sql b/db/function/view_lease_to_pay.sql index f01483a..5bef075 100644 --- a/db/function/view_lease_to_pay.sql +++ b/db/function/view_lease_to_pay.sql @@ -4,13 +4,14 @@ -- Call using 'select * from table(view_lease_to_pay(pid));' -CREATE OR REPLACE FUNCTION view_lease_to_pay ( +CREATE OR REPLACE FUNCTION lease_to_pay ( pid number ) RETURN lease_pay_table AS tbl_out lease_pay_table; BEGIN SELECT lease_pay_row( + id, prop_id, apt, start_date, diff --git a/db/function/view_prop_amen_to_pay.sql b/db/function/view_prop_amen_to_pay.sql index eebecf8..7edbc9e 100644 --- a/db/function/view_prop_amen_to_pay.sql +++ b/db/function/view_prop_amen_to_pay.sql @@ -5,7 +5,12 @@ CREATE OR REPLACE FUNCTION prop_amen_to_pay ( AS tbl_out amen_pay_table; BEGIN - SELECT amen_pay_row(amenity.id, amenity, cost) + SELECT amen_pay_row( + amenity.id, + amenity, + cost, + CEIL(MONTHS_BETWEEN(CURRENT_TIMESTAMP, date_paid)) + ) BULK COLLECT INTO tbl_out FROM -- Check amenities that correspond to the person's lease diff --git a/db/types/amen_payment_row.sql b/db/types/amen_payment_row.sql index c1ed703..0c15ccd 100644 --- a/db/types/amen_payment_row.sql +++ b/db/types/amen_payment_row.sql @@ -1,5 +1,6 @@ CREATE OR REPLACE TYPE amen_pay_row as OBJECT( amen_id number, amenity VARCHAR2(255), - cost number + cost number, + months_outstanding number ); \ No newline at end of file diff --git a/db/types/lease_payment_row.sql b/db/types/lease_payment_row.sql index c0f89e4..6fb52d0 100644 --- a/db/types/lease_payment_row.sql +++ b/db/types/lease_payment_row.sql @@ -1,4 +1,5 @@ CREATE OR REPLACE TYPE lease_pay_row as OBJECT( + lease_id number, prop_id number, apt varchar2(5), start_date date, diff --git a/numa/src/main/java/numa/Exceptions/MenuException.java b/numa/src/main/java/numa/Exceptions/MenuException.java index 77cd382..f7914cb 100644 --- a/numa/src/main/java/numa/Exceptions/MenuException.java +++ b/numa/src/main/java/numa/Exceptions/MenuException.java @@ -4,4 +4,8 @@ public class MenuException extends Exception { public MenuException() { super("Returning to the main menu..."); } + + public MenuException(String string) { + super(string + "\n\nReturning to the main menu..."); + } } diff --git a/numa/src/main/java/numa/Portals/ResidentPortal.java b/numa/src/main/java/numa/Portals/ResidentPortal.java index 49a4e38..9460e59 100644 --- a/numa/src/main/java/numa/Portals/ResidentPortal.java +++ b/numa/src/main/java/numa/Portals/ResidentPortal.java @@ -1,13 +1,21 @@ package numa.Portals; import java.io.IOException; +import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; +import java.sql.Types; import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +import javax.naming.spi.DirStateFactory.Result; +import javax.swing.plaf.synth.SynthScrollPaneUI; import numa.Reader; import numa.Exceptions.*; @@ -189,8 +197,143 @@ public void resInfo() throws SQLException, NumberFormatException, IOException, E } /** Show all payments that need to be made and some details */ - public void makePayment() { - + public void makePayment() throws SQLException, MenuException, IOException { + try ( + PreparedStatement getLeaseId = conn.prepareStatement("select id, prop_id, apt, start_date from lease natural join apartment where lease.id in (select lease_id from person_on_lease where person_id = ?)"); + PreparedStatement getLeaseToPay = conn.prepareStatement("select * from table(lease_to_pay(?))"); + PreparedStatement getPropAmenToPay = conn.prepareStatement("select * from table(prop_amen_to_pay(?, ?))"); + PreparedStatement getAptAmenToPay = conn.prepareStatement("select * from table(apt_amen_to_pay(?, ?, ?))"); + CallableStatement makePayment = conn.prepareCall("{ call make_payment(?,?,?,?,?,?,?) }"); + Statement getDefaultPayment = conn.createStatement(); + ) { + Integer leaseId; + Integer propId; + String apt; + Date leaseStart; + + getLeaseId.setInt(1, resId); + ResultSet res = getLeaseId.executeQuery(); + + if (res.next()) { + leaseId = res.getInt("id"); + propId = res.getInt("prop_id"); + apt = res.getString("apt"); + leaseStart = res.getDate("start_date"); + } else { + throw new MenuException("Unable to find resident's lease"); + } + + Date today = new Date(); + int counter = 1; + ArrayList tracker = new ArrayList(); + + getLeaseToPay.setInt(1, resId); + res = getLeaseToPay.executeQuery(); + if (res.next()) { + System.out.println(BOLD_ON + "Lease Payment" + BOLD_OFF); + int monthsOutstanding = res.getInt("months_outstanding"); + if (monthsOutstanding == 0) { + monthsOutstanding = getMonths(leaseStart, today); + } + + int rent = monthsOutstanding * res.getInt("rent_amount"); + tracker.add(new int[]{0, res.getInt("lease_id"), rent}); + System.out.printf("[%d] %s - $%d [%d Month(s) Rent Due]\n", counter++, res.getString("apt"), rent, monthsOutstanding); + System.out.println(); + } + + getPropAmenToPay.setInt(1, leaseId); + getPropAmenToPay.setInt(2, propId); + res = getPropAmenToPay.executeQuery(); + String outStr = ""; + while (res.next()) { + int monthsOutstanding = res.getInt("months_outstanding"); + if (monthsOutstanding == 0) { + monthsOutstanding = getMonths(leaseStart, today); + } + + int rent = monthsOutstanding * res.getInt("cost"); + tracker.add(new int[]{1, res.getInt("amen_id"), rent}); + outStr += String.format("[%d] %s - $%d [%d Month(s) Due]\n", counter++, res.getString("amenity"), rent, monthsOutstanding); + } + + getAptAmenToPay.setInt(1, resId); + getAptAmenToPay.setInt(2, propId); + getAptAmenToPay.setString(3, apt); + res = getAptAmenToPay.executeQuery(); + while (res.next()) { + int monthsOutstanding = res.getInt("months_outstanding"); + if (monthsOutstanding == 0) { + monthsOutstanding = getMonths(leaseStart, today); + } + + int rent = monthsOutstanding * res.getInt("cost"); + tracker.add(new int[]{1, res.getInt("amen_id"), rent}); + outStr += String.format("[%d] %s - $%d [%d Month(s) Due]\n", counter++, res.getString("amenity"), rent, monthsOutstanding); + } + + if (outStr != "") { + System.out.println(BOLD_ON + "Amenities" + BOLD_OFF); + System.out.println(outStr); + } + + String in = input.getPrompt("Payments are made in full. For multiple payments, separate numbers with commas\nPay for: "); + String[] choices = in.split(","); + ArrayList errors = new ArrayList(); + + for (String choice: choices) { + try { + choice = choice.replaceAll("\\s+",""); + int index = Integer.parseInt(choice); + int[] map = tracker.get(index - 1); + + int payId; + res = getDefaultPayment.executeQuery("select preferred_payment from renter_info where person_id=" + resId); + if (res.next()) { + payId = res.getInt("preferred_payment"); + } else { + throw new MenuException("No payment information on file. Please set that up in 'My Info' first"); + } + + if (map[0] == 0) { + // Lease Payment + makePayment.setInt(1, -1); + makePayment.setInt(2, map[1]); + } else { + // Amenity Payment + makePayment.setInt(1, map[1]); + makePayment.setInt(2, -1); + } + + makePayment.setInt(3, payId); + makePayment.setInt(4, map[2]); + makePayment.setInt(5, resId); + makePayment.setString(6, ""); + makePayment.registerOutParameter(7, Types.NUMERIC); + + makePayment.execute(); + + int success = makePayment.getInt(7); + conn.commit(); + if (success != 0) + errors.add(choice); + + } catch (NumberFormatException e) { + System.out.printf("Payment %s is not a valid input\n", choice); + errors.add(choice); + } catch (SQLException e) { + errors.add(choice); + } catch (IndexOutOfBoundsException e) { + errors.add(choice); + } + } + + if (errors.size() != 0) { + System.out.println("Error paying for payments " + String.join(", ", errors)); + } else { + System.out.println("Payment successful. Thank you!"); + } + } } /** Read only of apartment details */ @@ -263,4 +406,17 @@ public void viewAptDetails() throws SQLException { } } } + + public int getMonths(Date start, Date end) throws SQLException { + Calendar startTime = new GregorianCalendar(); + Calendar endTime = new GregorianCalendar(); + + startTime.setTime(start); + endTime.setTime(end); + + int yearDiff = endTime.get(Calendar.YEAR) - startTime.get(Calendar.YEAR); + int monthDiff = endTime.get(Calendar.MONTH) - startTime.get(Calendar.MONTH); + + return yearDiff * 12 + monthDiff; + } }