diff --git a/src/main/java/de/tilman/transactions/Application.java b/src/main/java/de/tilman/transactions/Application.java index 96fff2e..ec94686 100644 --- a/src/main/java/de/tilman/transactions/Application.java +++ b/src/main/java/de/tilman/transactions/Application.java @@ -57,11 +57,11 @@ public class Application { } // XXX for dev - make H2 database available as jdbc:h2:mem:testdb at /console (http://stackoverflow.com/a/24727653/3761783) -// @Bean -// public ServletRegistrationBean h2servletRegistration() { -// ServletRegistrationBean registration = new ServletRegistrationBean(new WebServlet()); -// registration.addUrlMappings("/console/*"); -// return registration; -// } + @Bean + public ServletRegistrationBean h2servletRegistration() { + ServletRegistrationBean registration = new ServletRegistrationBean(new WebServlet()); + registration.addUrlMappings("/console/*"); + return registration; + } } diff --git a/src/main/java/de/tilman/transactions/SpringDataRestCustomization.java b/src/main/java/de/tilman/transactions/SpringDataRestCustomization.java index 230157e..23729e2 100644 --- a/src/main/java/de/tilman/transactions/SpringDataRestCustomization.java +++ b/src/main/java/de/tilman/transactions/SpringDataRestCustomization.java @@ -8,7 +8,6 @@ import de.tilman.transactions.domain.Account; import de.tilman.transactions.domain.Category; import de.tilman.transactions.domain.Transaction; import de.tilman.transactions.domain.User; -import de.tilman.transactions.domain.Withdrawal; @Component public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter { @@ -16,7 +15,6 @@ public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter // TODO Ask someone who knows better how to do all of this without exposing the IDs. Parsing URLs can't be the answer. @Override public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { - - config.exposeIdsFor(Account.class, Category.class, Transaction.class, User.class, Withdrawal.class); + config.exposeIdsFor(Account.class, Category.class, Transaction.class, User.class); } } diff --git a/src/main/java/de/tilman/transactions/domain/Account.java b/src/main/java/de/tilman/transactions/domain/Account.java index dc0f08d..4e5b02e 100644 --- a/src/main/java/de/tilman/transactions/domain/Account.java +++ b/src/main/java/de/tilman/transactions/domain/Account.java @@ -30,9 +30,6 @@ public class Account { @JoinTable(name = "account_user", joinColumns = @JoinColumn(name = "account_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id")) private List users; - @OneToMany(mappedBy = "account") - private List withdrawals; - public Long getId() { @@ -70,13 +67,5 @@ public class Account { public void setUsers(List users) { this.users = users; } - - public List getWithdrawals() { - return withdrawals; - } - - public void setWithdrawals(List withdrawals) { - this.withdrawals = withdrawals; - } } diff --git a/src/main/java/de/tilman/transactions/domain/Withdrawal.java b/src/main/java/de/tilman/transactions/domain/Withdrawal.java deleted file mode 100644 index b59d24a..0000000 --- a/src/main/java/de/tilman/transactions/domain/Withdrawal.java +++ /dev/null @@ -1,63 +0,0 @@ -package de.tilman.transactions.domain; - -import java.math.BigDecimal; -import java.util.Date; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToOne; - -@Entity -public class Withdrawal { - - @Id - @GeneratedValue - private Long id; - - @ManyToOne(optional = false) - private Account account; - - @ManyToOne(optional = false) - private User user; - - private BigDecimal amount; - private Date date; - - public Long getId() { - return id; - } - - public Account getAccount() { - return account; - } - - public void setAccount(Account account) { - this.account = account; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public BigDecimal getAmount() { - return amount; - } - - public void setAmount(BigDecimal amount) { - this.amount = amount; - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - -} diff --git a/src/main/java/de/tilman/transactions/repository/TransactionRepository.java b/src/main/java/de/tilman/transactions/repository/TransactionRepository.java index 2390a30..d41df02 100644 --- a/src/main/java/de/tilman/transactions/repository/TransactionRepository.java +++ b/src/main/java/de/tilman/transactions/repository/TransactionRepository.java @@ -26,15 +26,25 @@ public interface TransactionRepository extends PagingAndSortingRepository getDescriptionsByAccount(@Param("accountId") Long accountId, @Param("prefix") String prefix, Pageable pageable); @RestResource(path = "expenses") - @Query("SELECT t FROM Transaction t INNER JOIN t.account a WHERE a.id = :accountId AND t.creditor.id = :userId ORDER BY t.date DESC") + @Query("SELECT t FROM Transaction t WHERE t.account.id = :accountId AND t.creditor.id = :userId ORDER BY t.date DESC") List getTransactionsForCreditorByAccount(@Param("accountId") Long accountId, @Param("userId") Long userId); // http://localhost:8080/transactions/search/forAccount?accountId=2&size=10&sort=date,desc @RestResource(path = "forAccount") Page findByAccountId(@Param("accountId") Long accountId, Pageable pageable); + @RestResource(path = "withdrawals") + @Query("SELECT t FROM Transaction t WHERE t.account.id = :accountId AND t.category.id = (SELECT id FROM Category WHERE account_ID = :accountId AND position = (SELECT Max(position) FROM Category WHERE account_ID = :accountId)) AND t.creditor.id = :userId ORDER BY t.date DESC") + Page getWithdrawalsForUserByAccount(@Param("accountId") Long accountId, @Param("userId") Long userId, Pageable pageable); + + // http://localhost:8080/transactions/search/outstandings?accountId=1&userId=1 + @RestResource(path = "outstandings") +// @Query("SELECT t FROM Transaction t WHERE t.account.id = :accountId AND (t.creditor.id = :userId OR (t.category.id = (SELECT id FROM Category WHERE account_ID = :accountId AND position = (SELECT Max(position) FROM Category WHERE account_ID = :accountId)) AND t.creditor.id = :userId)) ORDER BY t.date DESC") + @Query("SELECT t FROM Transaction t WHERE t.account.id = :accountId AND (t.creditor.id = :userId OR (t.category.name = 'Private Entnahme' AND t.creditor.id = :userId)) ORDER BY t.date DESC") + Page getOutstandingsForUserByAccount(@Param("accountId") Long accountId, @Param("userId") Long userId, Pageable pageable); + } diff --git a/src/main/java/de/tilman/transactions/repository/WithdrawalRepository.java b/src/main/java/de/tilman/transactions/repository/WithdrawalRepository.java deleted file mode 100644 index e99bfa2..0000000 --- a/src/main/java/de/tilman/transactions/repository/WithdrawalRepository.java +++ /dev/null @@ -1,18 +0,0 @@ -package de.tilman.transactions.repository; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.repository.query.Param; -import org.springframework.data.rest.core.annotation.RestResource; - -import de.tilman.transactions.domain.Withdrawal; - -public interface WithdrawalRepository extends PagingAndSortingRepository { - - @RestResource(path = "forAccount") - @Query("SELECT w FROM Withdrawal w INNER JOIN w.account a WHERE a.id = :accountId AND w.user.id = :userId ORDER BY w.date DESC") - Page getWithdrawalsForUserByAccount(@Param("accountId") Long accountId, @Param("userId") Long userId, Pageable pageable); - -} diff --git a/src/main/resources/data-h2.sql b/src/main/resources/data-h2.sql index 7f96524..aa36cfa 100644 --- a/src/main/resources/data-h2.sql +++ b/src/main/resources/data-h2.sql @@ -1,10 +1,13 @@ INSERT INTO User (id, name, username) VALUES (1, 'Adam', 'adam@mail.com'), (2, 'Betty', 'betty@mail.com'), (3, 'Curt', 'curt@mail.com'); INSERT INTO Account (id, name, owner_id) VALUES (1, 'Gemeinschaftskonto', 1), (2, 'Konto Adam', 1); -INSERT INTO Withdrawal(id, account_id, amount, user_id, date) VALUES (1, 1, 20.00, 2, '2016-04-12 18:20:15'); -INSERT INTO Withdrawal(id, account_id, amount, user_id, date) VALUES (2, 1, 10.00, 1, '2016-04-14 10:03:00'); - -INSERT INTO Category (id, name, account_id, position) VALUES (1, 'Essen - Lebensmittel', 1, 2), (2, 'Einnahmen - Gehalt', 1, 1), (3, 'Essen - Arbeit', 1, 3), (4, 'Einnahmen - Gehalt', 2, 1), (5, 'Technik - Server und Hosting', 2, 2); +INSERT INTO Category (id, name, account_id, position) VALUES + (null, 'Essen - Lebensmittel', 1, 2), + (null, 'Einnahmen - Gehalt', 1, 1), + (null, 'Essen - Arbeit', 1, 3), + (null, 'Private Entnahme', 1, 4), + (null, 'Einnahmen - Gehalt', 2, 1), + (null, 'Technik - Server und Hosting', 2, 2); INSERT INTO Account_User (account_id, user_id) VALUES (1, 1), (1, 2), (1, 3), (2, 1); @@ -13,16 +16,19 @@ INSERT INTO Transaction (id, amount, account_id, category_id, date, description, (NULL, -2.21, 1, 1, '2016-04-10', 'Brot', null), (NULL, -3.41, 1, 1, '2016-04-12', 'Gemüse', null), (NULL, -7.81, 1, 3, '2016-04-19', 'Kantine', null), - (NULL, -4.81, 1, 3, '2016-04-18', 'Currywurst', 1), + (NULL, -4.81, 1, 3, '2016-04-18', 'Currywurst (Auslage Adam)', 1), (NULL, -4.50, 1, 3, '2016-04-19', 'Currywurst', null), (NULL, -4.50, 1, 3, '2016-04-20', 'Currywurst', null), (NULL, -4.50, 2, 3, '2016-04-20', 'Currywurst', null), (NULL, -4.09, 1, 3, '2016-04-18', 'Currywurst-Frühstück', null), (NULL, -4.90, 1, 3, '2016-04-18', 'Currywurst (Auslage Betty)', 2), (NULL, -8.90, 1, 3, '2016-04-18', 'Curry beim Inder (Auslage Adam)', 1), - (NULL, -12.00, 2, 3, '2016-04-18', 'Curry Thai', null), - (NULL, 1340.22, 2, 4, '2016-04-02', 'Gehalt Adam', null), - (NULL, -12.90, 2, 5, '2016-04-16', 'Host Europe', null); + + (NULL, -20, 1, 4, '2016-04-12 18:20:15', 'Entnahme Betty', 2), + (NULL, -10, 1, 4, '2016-04-14 10:03:00', 'Entnahme Adam', 1), + + (NULL, 1340.22, 2, 5, '2016-04-02', 'Gehalt Adam', null), + (NULL, -12.90, 2, 6, '2016-04-16', 'Host Europe', null); -- add as many transactions as needed @@ -56,4 +62,6 @@ INSERT INTO Transaction (id, amount, account_id, category_id, date, description, INSERT INTO Transaction (id, amount, account_id, category_id, date, description, creditor_id) VALUES (NULL, -1.50, 1, 3, '2016-04-01', 'Transaction28', null); Commit; INSERT INTO Transaction (id, amount, account_id, category_id, date, description, creditor_id) VALUES (NULL, -1.50, 1, 1, '2016-04-01', 'Transaction29', null); Commit; INSERT INTO Transaction (id, amount, account_id, category_id, date, description, creditor_id) VALUES (NULL, -1.50, 1, 3, '2016-04-01', 'Transaction30', null); Commit; -INSERT INTO Transaction (id, amount, account_id, category_id, date, description, creditor_id) VALUES (NULL, 1.50, 1, 4, CURRENT_TIMESTAMP()+1, 'LAST Transaction', null); Commit; +INSERT INTO Transaction (id, amount, account_id, category_id, date, description, creditor_id) VALUES (NULL, 1.50, 2, 5, CURRENT_TIMESTAMP()+1, 'LAST Transaction', null); Commit; + +--SCRIPT TO 'h2export.sql'; \ No newline at end of file diff --git a/src/main/resources/static/css/app.css b/src/main/resources/static/css/app.css index dc5725b..8faeed1 100644 --- a/src/main/resources/static/css/app.css +++ b/src/main/resources/static/css/app.css @@ -61,6 +61,10 @@ label { cursor: pointer; } +.color-black { + color: black; +} + .color-red { color: red; } diff --git a/src/main/resources/static/js/controllers.js b/src/main/resources/static/js/controllers.js index c37f72f..b90e6d5 100644 --- a/src/main/resources/static/js/controllers.js +++ b/src/main/resources/static/js/controllers.js @@ -23,53 +23,34 @@ transactionControllers.controller('TransactionListCtrl', [ '$scope', '$location' accountUsers.$promise.then(function(data) { $scope.accountUsers = accountUsers._embedded.users; - // initialize attributes for outstanding amounts - for (i = 0; i < $scope.accountUsers.length; i++) { - $scope.accountUsers[i].outstandingSum = 0.0; - } - - // get expenses for all users of the account + // get outstandings (expenses and withdrawals) for all users of the account var promises = new Array($scope.accountUsers.length); for (i = 0; i < $scope.accountUsers.length; i++) { - var resource = $resource('/transactions/search/expenses', { accountId: $scope.account.id, userId: $scope.accountUsers[i].id }).get(); + var resource = $resource('/transactions/search/outstandings', { accountId: $scope.account.id, userId: $scope.accountUsers[i].id }).get(); promises[i] = resource.$promise; } $q.all(promises).then(function(data) { for (i = 0; i < data.length; i++) { - $scope.accountUsers[i].expenses = new Array(data[i]._embedded.transactions.length); - var expenseSum = 0; + $scope.accountUsers[i].outstandings = new Array(data[i]._embedded.transactions.length); + $scope.accountUsers[i].outstandingSum = 0.0; + for (j = 0; j < data[i]._embedded.transactions.length; j++) { - $scope.accountUsers[i].expenses[j] = new Object(); - $scope.accountUsers[i].expenses[j].date = data[i]._embedded.transactions[j].date; - $scope.accountUsers[i].expenses[j].category = data[i]._embedded.transactions[j].category.name; - $scope.accountUsers[i].expenses[j].amount = numberToAmount(data[i]._embedded.transactions[j].amount); - $scope.accountUsers[i].expenses[j].description = data[i]._embedded.transactions[j].description; - expenseSum = expenseSum + data[i]._embedded.transactions[j].amount; + $scope.accountUsers[i].outstandings[j] = new Object(); + $scope.accountUsers[i].outstandings[j].date = data[i]._embedded.transactions[j].date; + $scope.accountUsers[i].outstandings[j].description = data[i]._embedded.transactions[j].description; + $scope.accountUsers[i].outstandings[j].category = data[i]._embedded.transactions[j].category.name; + + if ($scope.accountUsers[i].outstandings[j].category === 'Private Entnahme') { // magic strings ftw + $scope.accountUsers[i].outstandingSum += data[i]._embedded.transactions[j].amount; + $scope.accountUsers[i].outstandings[j].amount = numberToAmount(data[i]._embedded.transactions[j].amount); + } + else { + $scope.accountUsers[i].outstandingSum -= data[i]._embedded.transactions[j].amount; + $scope.accountUsers[i].outstandings[j].amount = numberToAmount(-data[i]._embedded.transactions[j].amount); + } } - $scope.accountUsers[i].outstandingSum -= expenseSum; - $scope.accountUsers[i].outstandingAmount = numberToAmount($scope.accountUsers[i].outstandingSum); - } - }); - - // get withdrawals for all users of the account - var promises = new Array($scope.accountUsers.length); - for (i = 0; i < $scope.accountUsers.length; i++) { - var resource = $resource('/withdrawals/search/forAccount', { accountId: $scope.account.id, userId: $scope.accountUsers[i].id }).get(); - promises[i] = resource.$promise; - } - - $q.all(promises).then(function(data) { - for (i = 0; i < data.length; i++) { - $scope.accountUsers[i].withdrawals = new Array(data[i]._embedded.withdrawals.length); - var withdrawnSum = 0; - for (j = 0; j < data[i]._embedded.withdrawals.length; j++) { - $scope.accountUsers[i].withdrawals[j] = new Object(); - $scope.accountUsers[i].withdrawals[j].date = data[i]._embedded.withdrawals[j].date; - $scope.accountUsers[i].withdrawals[j].amount = numberToAmount(data[i]._embedded.withdrawals[j].amount); - withdrawnSum = withdrawnSum + data[i]._embedded.withdrawals[j].amount; - } - $scope.accountUsers[i].outstandingSum -= withdrawnSum; + $scope.accountUsers[i].outstandingAmount = numberToAmount($scope.accountUsers[i].outstandingSum); } }); @@ -116,7 +97,7 @@ transactionControllers.controller('TransactionListCtrl', [ '$scope', '$location' var userLabels = document.getElementsByClassName('userLabel'); // if this is selected to be a withdrawal, preselect the current user and lock the radio buttons - if ($scope.transaction.category.id == -1) { + if ($scope.transaction.category.name === 'Private Entnahme') { for (i = 0; i < userLabels.length; i++) { console.log(userLabels[i].innerHTML.substr(-$scope.userinfo.name.length-6)); if (userLabels[i].innerHTML.indexOf($scope.userinfo.name) >= 0) { @@ -155,47 +136,16 @@ transactionControllers.controller('TransactionListCtrl', [ '$scope', '$location' var categories = $resource('/categories/search/listForAccount', { accountId: $scope.accounts[0].id }).get(); categories.$promise.then(function(data) { $scope.categories = categories._embedded.categories; - - //$scope.categories.push({id: -1, name: '────────────────', position: 9999, disabled: true}); - $scope.categories.push({id: -1, name: 'private Entnahme', position: 10000, _links: { self: {href: 'withdrawal'}}}); - $scope.refreshList(); }); }); }); - } $scope.postTransaction = function() { - - var amount = amountToNumber($scope.transaction.amount); - - // handle withdrawals - if ($scope.transaction.category._links.self.href === 'withdrawal') { - if (amount.charAt(0) === '-') { - amount = amount.substr(1); - } - - var Withdrawal = $resource('/withdrawals'); - - var newWithdrawal = new Withdrawal({ - "account" : $scope.account._links.self.href, - "amount" : amount, - "date" : $scope.transaction.date, - "user" : $scope.userinfo._links.self.href - }); - - newWithdrawal.$save(function(withdrawal) { - $scope.refreshList(); - $scope.lastSubmission = newWithdrawal; - }); - - return; - } - var newTransaction = new Transaction({ "account" : $scope.account._links.self.href, - "amount" : amount, + "amount" : amountToNumber($scope.transaction.amount), "date" : $scope.transaction.date, "description" : $scope.transaction.description, "category" : $scope.transaction.category._links.self.href, @@ -206,7 +156,6 @@ transactionControllers.controller('TransactionListCtrl', [ '$scope', '$location' $scope.refreshList(); $scope.lastSubmission = newTransaction; }); - }; $scope.deleteLastSubmission = function() { @@ -289,8 +238,8 @@ transactionControllers.controller('TransactionListCtrl', [ '$scope', '$location' $scope.openExpenses = function(user) { var modalInstance = $uibModal.open({ - templateUrl: 'expensesTemplate.html', - controller: 'ExpensesModalCtrl', + templateUrl: 'outstandingsTemplate.html', + controller: 'OutstandingsModalCtrl', resolve: { accountUser: user } @@ -299,7 +248,7 @@ transactionControllers.controller('TransactionListCtrl', [ '$scope', '$location' modalInstance.result.then(function() { refreshExpenses(); }, function () { - $log.info('ExpensesModal dismissed ' + new Date()); + $log.info('OutstandingsModal dismissed ' + new Date()); }); }; @@ -325,7 +274,7 @@ transactionControllers.controller('DetailsModalCtrl', [ '$scope', '$resource', ' for (i = 0; i < $scope.categories.length; i++) { if ($scope.categories[i].name == $scope.transaction.category.name) { - $scope.transaction.category = $scope.categories[i]; + $scope.transaction.category = $scope.categories[i]; break; } } @@ -360,7 +309,7 @@ transactionControllers.controller('DetailsModalCtrl', [ '$scope', '$resource', ' } } ]); -transactionControllers.controller('ExpensesModalCtrl', [ '$scope', '$uibModalInstance', 'accountUser', function($scope, $uibModalInstance, accountUser) { +transactionControllers.controller('OutstandingsModalCtrl', [ '$scope', '$uibModalInstance', 'accountUser', function($scope, $uibModalInstance, accountUser) { $scope.accountUser = accountUser; diff --git a/src/main/resources/static/partials/transaction-list.html b/src/main/resources/static/partials/transaction-list.html index 73e9e63..f960656 100644 --- a/src/main/resources/static/partials/transaction-list.html +++ b/src/main/resources/static/partials/transaction-list.html @@ -91,7 +91,7 @@ {{transaction.date | date:'dd.MM.yyyy'}} {{transaction.category.name}} - {{transaction.amount}} € + {{transaction.amount}} € {{transaction.description}} @@ -176,13 +176,12 @@ -