removed Withdrawal entity

This commit is contained in:
2016-07-13 23:53:55 +02:00
parent 2c92dd00fe
commit a3d170be77
10 changed files with 76 additions and 214 deletions
@@ -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;
}
}
@@ -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);
}
}
@@ -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<User> users;
@OneToMany(mappedBy = "account")
private List<Withdrawal> withdrawals;
public Long getId() {
@@ -71,12 +68,4 @@ public class Account {
this.users = users;
}
public List<Withdrawal> getWithdrawals() {
return withdrawals;
}
public void setWithdrawals(List<Withdrawal> withdrawals) {
this.withdrawals = withdrawals;
}
}
@@ -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;
}
}
@@ -26,15 +26,25 @@ public interface TransactionRepository extends PagingAndSortingRepository<Transa
// http://localhost:8080/transactions/search/descriptions?accountId=1&prefix=Kan
// http://localhost:8080/transactions/search/descriptions?accountId=1&prefix=C&size=2
@RestResource(path = "descriptions")
@Query("SELECT t FROM Transaction t INNER JOIN t.account a WHERE a.id = :accountId AND LOWER(t.description) LIKE :prefix% ORDER BY t.date DESC")
@Query("SELECT t FROM Transaction t WHERE t.account.id = :accountId AND LOWER(t.description) LIKE :prefix% ORDER BY t.date DESC")
Page<Transaction> 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<Transaction> 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<Transaction> 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<Transaction> 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<Transaction> getOutstandingsForUserByAccount(@Param("accountId") Long accountId, @Param("userId") Long userId, Pageable pageable);
}
@@ -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<Withdrawal, Long> {
@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<Withdrawal> getWithdrawalsForUserByAccount(@Param("accountId") Long accountId, @Param("userId") Long userId, Pageable pageable);
}
+17 -9
View File
@@ -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';
+4
View File
@@ -61,6 +61,10 @@ label {
cursor: pointer;
}
.color-black {
color: black;
}
.color-red {
color: red;
}
+25 -76
View File
@@ -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].outstandingSum -= expenseSum;
$scope.accountUsers[i].outstandingAmount = numberToAmount($scope.accountUsers[i].outstandingSum);
}
});
$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;
// 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;
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 -= 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;
@@ -91,7 +91,7 @@
<tr ng-repeat="transaction in transactions" ng-click="openDetails(transaction)" class="clickable">
<td>{{transaction.date | date:'dd.MM.yyyy'}}</td>
<td>{{transaction.category.name}}</td>
<td align="right" class="{{transaction.creditor.name ? 'creditor-' + transaction.creditor.id : ''}}">{{transaction.amount}}&nbsp;&euro;</td>
<td align="right" class="{{transaction.creditor.name ? 'creditor-' + transaction.creditor.id : ''}}"><span ng-class="transaction.amount.charAt(0) === '+' ? 'color-green' : 'color-black'">{{transaction.amount}}&nbsp;&euro;</span></td>
<td>{{transaction.description}}</td>
</tr>
</table>
@@ -176,13 +176,12 @@
<!-- pre style="font-size: 75%; color: black;">{{transaction | json}}</pre -->
</script>
<script type="text/ng-template" id="expensesTemplate.html">
<script type="text/ng-template" id="outstandingsTemplate.html">
<div class="modal-header">
<h3 class="modal-title">{{accountUser.name}} <span style="margin: 0" ng-class="accountUser.outstandingSum >= 0 ? 'color-green' : 'color-red'">{{accountUser.outstandingAmount}}&nbsp;</span></h3>
<h3 class="modal-title">{{accountUser.name}} <span ng-class="accountUser.outstandingSum >= 0 ? 'color-green' : 'color-red'">{{accountUser.outstandingAmount}}&nbsp;</span></h3>
</div>
<div class="modal-body">
<div ng-show="accountUser.expenses.length > 0">
<h4 class="modal-title">Auslagen</h4>
<div ng-show="accountUser.outstandings.length > 0">
<table class="listing">
<tr>
<th>Datum</th>
@@ -190,30 +189,16 @@
<th>Betrag</th>
<th>Beschreibung</th>
</tr>
<tr ng-repeat="expense in accountUser.expenses">
<td>{{expense.date | date:'dd.MM.yyyy'}}</td>
<td>{{expense.category}}</td>
<td align="right">{{expense.amount}}&nbsp;&euro;</td>
<td>{{expense.description}}</td>
<tr ng-repeat="outstanding in accountUser.outstandings">
<td>{{outstanding.date | date:'dd.MM.yyyy'}}</td>
<td>{{outstanding.category}}</td>
<td align="right"><span ng-class="outstanding.amount.charAt(0) === '+' ? 'color-green' : 'color-red'">{{outstanding.amount}}&nbsp;&euro;</span></td>
<td>{{outstanding.description}}</td>
</tr>
</table>
</div>
<div ng-show="accountUser.withdrawals.length > 0">
<h4 class="modal-title" style="margin-top: 3.5ex;">Entnahmen</h4>
<table class="listing">
<tr>
<th>Datum</th>
<th>Betrag</th>
</tr>
<tr ng-repeat="withdrawal in accountUser.withdrawals">
<td>{{withdrawal.date | date:'dd.MM.yyyy'}}</td>
<td align="right">{{withdrawal.amount}}&nbsp;&euro;</td>
</tr>
</table>
</div>
<div ng-show="accountUser.expenses.length == 0 && accountUser.withdrawals.length == 0">
<div ng-show="accountUser.outstandings.length == 0">
<i>Keine Auslagen oder Entnahmen für {{accountUser.name}}</i>
</div>