Skip to content

Commit

Permalink
Merge pull request #3 from agilitytestbed/features/balancehistory
Browse files Browse the repository at this point in the history
Features/balancehistory
  • Loading branch information
dkooij authored May 13, 2018
2 parents 74f0a5c + 564dd1c commit 0723359
Show file tree
Hide file tree
Showing 8 changed files with 403 additions and 21 deletions.
21 changes: 19 additions & 2 deletions sql_queries_and_updates.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ WHERE user_id = ?
LIMIT ?
OFFSET ?;



increaseHighestCategoryRuleID(user_id):
UPDATE User_Table
SET highest_category_rule_id = highest_category_rule_id + 1
Expand Down Expand Up @@ -156,7 +154,26 @@ AND description LIKE ?
AND external_iban LIKE ?
AND type LIKE ?;

getDepositsOnDate(user_id, date):
SELECT SUM(amount)
FROM Transaction_Table
WHERE user_id = ?
AND date <= ?
AND type = 'deposit';

getWithdrawalsOnDate(user_id, date):
SELECT SUM(amount)
FROM Transaction_Table
WHERE user_id = ?
AND date <= ?
AND type = 'withdrawal';

getTransactionsAfterDate(user_id, date):
SELECT transaction_id, date, amount, description, external_iban, type
FROM Transaction_Table
WHERE user_id = ?
AND date > ?
ORDER BY date ASC;

linkTransactionToCategory(user_id, transaction_id, category_id):
INSERT INTO Transaction_Category (user_id, transaction_id, category_id)
Expand Down
74 changes: 64 additions & 10 deletions src/main/java/nl/utwente/ing/api/MainRestController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import nl.utwente.ing.exception.InvalidSessionIDException;
import nl.utwente.ing.exception.ResourceNotFoundException;
import nl.utwente.ing.misc.date.IntervalPeriod;
import nl.utwente.ing.model.Model;
import nl.utwente.ing.model.bean.BalanceCandlestick;
import nl.utwente.ing.model.bean.Category;
import nl.utwente.ing.model.bean.CategoryRule;
import nl.utwente.ing.model.bean.Transaction;
Expand Down Expand Up @@ -124,6 +126,7 @@ public ResponseEntity postTransaction(@RequestParam(value = "session_id", defaul
if (!t.getType().equals("deposit") && !t.getType().equals("withdrawal")) {
return ResponseEntity.status(405).body("Invalid input given (type should be 'deposit' or 'withdrawal')");
}
t.setAmount(Math.abs(t.getAmount()));
if (t.getDescription() == null) {
t.setDescription("");
}
Expand Down Expand Up @@ -194,6 +197,7 @@ public ResponseEntity putTransaction(@RequestParam(value = "session_id", default
!t.getType().equals("deposit") && !t.getType().equals("withdrawal")) {
return ResponseEntity.status(405).body("Invalid input given (type should be 'deposit' or 'withdrawal')");
}
t.setAmount(Math.abs(t.getAmount()));
try {
String sessionID = this.getSessionID(pSessionID, hSessionID);
long transactionIDLong = Long.parseLong(transactionID);
Expand Down Expand Up @@ -492,19 +496,19 @@ public ResponseEntity getCategoryRule(@RequestParam(value = "session_id", defaul
/**
* Method used to update a certain CategoryRule belonging to the user issuing the current request.
*
* @param pSessionID The sessionID specified in the request parameters.
* @param hSessionID The sessionID specified in the HTTP header.
* @param pSessionID The sessionID specified in the request parameters.
* @param hSessionID The sessionID specified in the HTTP header.
* @param categoryRuleID The categoryRuleID of the CategoryRule that will be updated.
* @param cr The CategoryRule object as specified in the json HTTP body.
* @param cr The CategoryRule object as specified in the json HTTP body.
* @return A ResponseEntity containing a HTTP status code and either a status message or
* the CategoryRule updated using this method.
*/
@RequestMapping(method = RequestMethod.PUT,
value = RestControllerConstants.URI_PREFIX + "/categoryRules/{categoryRuleID}")
public ResponseEntity putCategoryRule(@RequestParam(value = "session_id", defaultValue = "") String pSessionID,
@RequestHeader(value = "X-session-ID", defaultValue = "") String hSessionID,
@PathVariable String categoryRuleID,
@RequestBody CategoryRule cr) {
@RequestHeader(value = "X-session-ID", defaultValue = "") String hSessionID,
@PathVariable String categoryRuleID,
@RequestBody CategoryRule cr) {
if (cr == null || cr.getDescription() == null || cr.getiBAN() == null || cr.getType() == null ||
cr.getCategory_id() <= 0) {
return ResponseEntity.status(405).body("Invalid input given");
Expand All @@ -528,16 +532,16 @@ public ResponseEntity putCategoryRule(@RequestParam(value = "session_id", defaul
/**
* Method used to remove a certain CategoryRule belonging to the user issuing the current request.
*
* @param pSessionID The sessionID specified in the request parameters.
* @param hSessionID The sessionID specified in the HTTP header.
* @param pSessionID The sessionID specified in the request parameters.
* @param hSessionID The sessionID specified in the HTTP header.
* @param categoryRuleID The categoryRuleID of the CategoryRule that will be deleted.
* @return A ResponseEntity containing a HTTP status code and a status message.
*/
@RequestMapping(method = RequestMethod.DELETE,
value = RestControllerConstants.URI_PREFIX + "/categoryRules/{categoryRuleID}")
public ResponseEntity deleteCategoryRule(@RequestParam(value = "session_id", defaultValue = "") String pSessionID,
@RequestHeader(value = "X-session-ID", defaultValue = "") String hSessionID,
@PathVariable String categoryRuleID) {
@RequestHeader(value = "X-session-ID", defaultValue = "") String hSessionID,
@PathVariable String categoryRuleID) {
try {
String sessionID = this.getSessionID(pSessionID, hSessionID);
long categoryRuleIDLong = Long.parseLong(categoryRuleID);
Expand All @@ -550,4 +554,54 @@ public ResponseEntity deleteCategoryRule(@RequestParam(value = "session_id", def
}
}

/**
* Method used to retrieve balance history of to the user issuing the current request.
*
* @param pSessionID The sessionID specified in the request parameters.
* @param hSessionID The sessionID specified in the HTTP header.
* @param interval The interval size specifying the length of intervals (default = "month") for which the balance
* history should be computed.
* @param intervals The amount of intervals for which the balance history should be computed.
* @return A ResponseEntity containing a HTTP status code and either a status message or
* an ArrayList of BalanceCandlestick of balance history based on the parameters specified by the user.
*/
@RequestMapping(method = RequestMethod.GET,
value = RestControllerConstants.URI_PREFIX + "/balance/history")
public ResponseEntity getBalanceHistory(@RequestParam(value = "session_id", defaultValue = "") String pSessionID,
@RequestHeader(value = "X-session-ID", defaultValue = "") String hSessionID,
@RequestParam(value = "interval", defaultValue = "month") String interval,
@RequestParam(value = "intervals", defaultValue = "24") String intervals) {
int amount = 24;
try {
amount = Integer.parseInt(intervals);
} catch (NumberFormatException e) {
// Do nothing
}

IntervalPeriod intervalPeriod;
if (interval.equals("year")) {
intervalPeriod = IntervalPeriod.YEAR;
} else if (interval.equals("month")) {
intervalPeriod = IntervalPeriod.MONTH;
} else if (interval.equals("week")) {
intervalPeriod = IntervalPeriod.WEEK;
} else if (interval.equals("day")) {
intervalPeriod = IntervalPeriod.DAY;
} else if (interval.equals("hour")) {
intervalPeriod = IntervalPeriod.HOUR;
} else {
return ResponseEntity.status(405).body("Invalid input given");
}

try {
String sessionID = this.getSessionID(pSessionID, hSessionID);
ArrayList<BalanceCandlestick> balanceCandlesticks =
model.getBalanceHistory(sessionID, intervalPeriod, amount);
return ResponseEntity.status(200).body(balanceCandlesticks);
} catch (InvalidSessionIDException e) {
return ResponseEntity.status(401).body("Session ID is missing or invalid");
}
}


}
82 changes: 82 additions & 0 deletions src/main/java/nl/utwente/ing/misc/date/IntervalHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package nl.utwente.ing.misc.date;

import java.time.LocalDateTime;

/**
* The IntervalHelper class.
* Used to generate intervals and compare dates.
*
* @author Daan Kooij
*/
public class IntervalHelper {

/**
* Method used to generate a certain number of intervals with certain size.
* The generation of intervals is done by taking the current datetime and and putting the resulting edges of the
* intervals in an array in the form of LocalDateTime objects.
* <p>
* Example: suppose the current date is 13 May 2018 and you want to generate five intervals with sizes of one day
* each. Then you specify intervalPeriod to be IntervalPeriod.DAY and amount to be 5. The returned array will then
* be: [8 May 2018, 9 May 2018, 10 May 2018, 11 May 2018, 12 May 2018, 13 May 2018].
* <p>
* Note that the size of the array is equal to the amount of intervals plus one.
*
* @param intervalPeriod The size of the intervals to be generated.
* @param amount The amount of intervals to be generated.
* @return An array containing (amount
*/
public static LocalDateTime[] getIntervals(IntervalPeriod intervalPeriod, int amount) {
LocalDateTime[] intervals = new LocalDateTime[amount + 1];
intervals[amount] = LocalDateTime.now();

if (intervalPeriod == IntervalPeriod.YEAR) {
for (int i = amount - 1; i >= 0; i--) {
intervals[i] = intervals[i + 1].minusYears(1);
}
} else if (intervalPeriod == IntervalPeriod.MONTH) {
for (int i = amount - 1; i >= 0; i--) {
intervals[i] = intervals[i + 1].minusMonths(1);
}
} else if (intervalPeriod == IntervalPeriod.WEEK) {
for (int i = amount - 1; i >= 0; i--) {
intervals[i] = intervals[i + 1].minusWeeks(1);
}
} else if (intervalPeriod == IntervalPeriod.DAY) {
for (int i = amount - 1; i >= 0; i--) {
intervals[i] = intervals[i + 1].minusDays(1);
}
} else {
for (int i = amount - 1; i >= 0; i--) {
intervals[i] = intervals[i + 1].minusHours(1);
}
}

return intervals;
}

/**
* Method used to convert a LocalDateTime object to a String, in the format that the DPA uses.
*
* @param localDateTime The LocalDateTime object that should be converted to a String.
* @return A String object in the format that the DPA uses that reflects the converted LocalDateTime object.
*/
public static String dateToString(LocalDateTime localDateTime) {
return localDateTime.toString() + "Z";
}

/**
* Method used to check whether the date contained in a certain LocalDateTime object is smaller than the date
* contained in a certain String object.
*
* @param date1 The LocalDateTime object for which it will be checked if the contained date is smaller than the
* contained date in s.
* @param s The String object for which it will be checked whether the contained date is bigger than or equal
* to the contained date in date1.
* @return A boolean indicating whether the date contained in date1 is smaller than the date contained in s.
*/
public static boolean isSmallerThan(LocalDateTime date1, String s) {
LocalDateTime date2 = LocalDateTime.parse(s.split("Z")[0]);
return date1.compareTo(date2) < 0;
}

}
13 changes: 13 additions & 0 deletions src/main/java/nl/utwente/ing/misc/date/IntervalPeriod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nl.utwente.ing.misc.date;

/**
* The IntervalPeriod enum.
* Used to enumerate the possible interval sizes.
*
* @author Daan Kooij
*/
public enum IntervalPeriod {

HOUR, DAY, WEEK, MONTH, YEAR;

}
18 changes: 14 additions & 4 deletions src/main/java/nl/utwente/ing/model/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

import nl.utwente.ing.exception.InvalidSessionIDException;
import nl.utwente.ing.exception.ResourceNotFoundException;
import nl.utwente.ing.model.bean.Category;
import nl.utwente.ing.model.bean.CategoryRule;
import nl.utwente.ing.model.bean.Session;
import nl.utwente.ing.model.bean.Transaction;
import nl.utwente.ing.misc.date.IntervalPeriod;
import nl.utwente.ing.model.bean.*;

import java.util.ArrayList;

Expand Down Expand Up @@ -196,4 +194,16 @@ CategoryRule putCategoryRule(String sessionID, CategoryRule categoryRule)
void deleteCategoryRule(String sessionID, long categoryRuleID)
throws InvalidSessionIDException, ResourceNotFoundException;

/**
* Method used to retrieve balance history information of a certain user in the form of a list of
* BalanceCandlesticks.
*
* @param sessionID The sessionID of the user.
* @param intervalPeriod The IntervalPeriod specifying the span of intervals.
* @param amount The amount of intervals for which BalanceCandlesticks should be generated.
* @return The balance history information of a certain user in the form of a list of BalanceCandlesticks.
*/
ArrayList<BalanceCandlestick> getBalanceHistory(String sessionID, IntervalPeriod intervalPeriod, int amount)
throws InvalidSessionIDException;

}
91 changes: 91 additions & 0 deletions src/main/java/nl/utwente/ing/model/bean/BalanceCandlestick.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package nl.utwente.ing.model.bean;

/**
* The Balance Candlestick class.
* Used to store balance information about the balance information of a certain interval.
*
* @author Daan Kooij
*/
public class BalanceCandlestick {

private float open, close, high, low, volume;

/**
* The constructor of BalanceCandlestick.
* Initially, only the opening balance is specified, after which this balance can be modified by using the mutate
* method. Along the way, this bean keeps track of the opening balance, the closing balance, the highest balance,
* the lowest balance and the volume of all the mutations combined.
*
* @param open The opening balance of this BalanceCandlestick.
*/
public BalanceCandlestick(float open) {
this.open = open;
this.close = open;
this.high = open;
this.low = open;
this.volume = 0;
}

/**
* Method used to retrieve the opening balance of BalanceCandlestick.
*
* @return The opening balance of BalanceCandlestick.
*/
public float getOpen() {
return open;
}

/**
* Method used to retrieve the closing balance of BalanceCandlestick.
*
* @return The closing balance of BalanceCandlestick.
*/
public float getClose() {
return close;
}

/**
* Method used to retrieve the highest balance in the lifetime of BalanceCandlestick.
*
* @return The highest balance in the lifetime of BalanceCandlestick.
*/
public float getHigh() {
return high;
}

/**
* Method used to retrieve the lowest balance in the lifetime of BalanceCandlestick.
*
* @return The lowest balance in the lifetime of BalanceCandlestick.
*/
public float getLow() {
return low;
}

/**
* Method used to retrieve the volume of all the mutations done on BalanceCandlestick combined.
*
* @return The volume of all the mutations done on BalanceCandlestick combined.
*/
public float getVolume() {
return volume;
}

/**
* Method used to indicate a mutation of the balance of BalanceCandlestick.
* Along the way, this method updates the closing balance, the highest balance, the lowest balance
* and the volume of all the mutations combined accordingly.
*
* @param amount The value with which the balance of BalanceCandlestick should be mutated.
*/
public void mutation(float amount) {
close += amount;
if (close > high) {
high = close;
} else if (close < low) {
low = close;
}
volume += Math.abs(amount);
}

}
Loading

0 comments on commit 0723359

Please sign in to comment.