Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added a bit of validation and a bit of styling

  • Loading branch information...
commit be6482f0d0a762326902d6a1a1ad84e3fdff6fb6 1 parent da5d86c
@jettro jettro authored
View
26 app/src/main/java/org/axonframework/samples/trader/app/query/portfolio/PortfolioEntry.java
@@ -37,6 +37,32 @@
/*-------------------------------------------------------------------------------------------*/
/* utility functions */
/*-------------------------------------------------------------------------------------------*/
+ public long obtainAmountOfAvailableItemsFor(String identifier) {
+ long possession = obtainAmountOfItemsInPossessionFor(identifier);
+ long reserved = obtainAmountOfReservedItemsFor(identifier);
+ return possession - reserved;
+ }
+
+ public long obtainAmountOfReservedItemsFor(String identifier) {
+ ItemEntry item = findReservedItemByIdentifier(identifier);
+ if (null == item) {
+ return 0;
+ }
+ return item.getAmount();
+ }
+
+ public long obtainAmountOfItemsInPossessionFor(String identifier) {
+ ItemEntry item = findItemInPossession(identifier);
+ if (null == item) {
+ return 0;
+ }
+ return item.getAmount();
+ }
+
+ public long obtainMoneyToSpend() {
+ return amountOfMoney - reservedAmountOfMoney;
+ }
+
public ItemEntry findReservedItemByIdentifier(String identifier) {
return itemsReserved.get(identifier);
}
View
56 app/src/test/java/org/axonframework/samples/trader/app/query/portfolio/PortfolioEntryTest.java
@@ -23,28 +23,54 @@
* @author Jettro Coenradie
*/
public class PortfolioEntryTest {
+ private static final long AMOUNT_ITEMS = 100;
+ private static final long AMOUNT_RESERVED = 40;
+ private static final int AMOUNT_SELL = 10;
+ private static final String ORDERBOOK_IDENTIFIER = "item1";
+ private static final int AMOUNT_OF_MONEY = 1000;
+ private static final int RESERVED_AMOUNT_OF_MONEY = 200;
+
@Test
public void testRemovingItems() {
+ PortfolioEntry portfolio = createDefaultPortfolio();
+
+ portfolio.removeReservedItem(ORDERBOOK_IDENTIFIER, AMOUNT_SELL);
+ portfolio.removeItemsInPossession(ORDERBOOK_IDENTIFIER, AMOUNT_SELL);
+
+ assertEquals(AMOUNT_RESERVED - AMOUNT_SELL, portfolio.findReservedItemByIdentifier(ORDERBOOK_IDENTIFIER).getAmount());
+ assertEquals(AMOUNT_ITEMS - AMOUNT_SELL, portfolio.findItemInPossession(ORDERBOOK_IDENTIFIER).getAmount());
+ }
+
+ @Test
+ public void testObtainAvailableItems() {
+ PortfolioEntry portfolio = createDefaultPortfolio();
+
+ assertEquals(AMOUNT_ITEMS - AMOUNT_RESERVED, portfolio.obtainAmountOfAvailableItemsFor(ORDERBOOK_IDENTIFIER));
+ }
+
+ @Test
+ public void testObtainBudget() {
+ PortfolioEntry portfolio = createDefaultPortfolio();
+ assertEquals(AMOUNT_OF_MONEY - RESERVED_AMOUNT_OF_MONEY, portfolio.obtainMoneyToSpend());
+ }
+
+ private PortfolioEntry createDefaultPortfolio() {
PortfolioEntry portfolio = new PortfolioEntry();
+
+ portfolio.addItemInPossession(createItem(AMOUNT_ITEMS));
+ portfolio.addReservedItem(createItem(AMOUNT_RESERVED));
+ portfolio.setAmountOfMoney(AMOUNT_OF_MONEY);
+ portfolio.setReservedAmountOfMoney(RESERVED_AMOUNT_OF_MONEY);
+ return portfolio;
+ }
+
+ private ItemEntry createItem(long amount) {
ItemEntry item1InPossession = new ItemEntry();
item1InPossession.setIdentifier("item1");
- item1InPossession.setAmount(100);
+ item1InPossession.setAmount(amount);
item1InPossession.setCompanyIdentifier("company1");
item1InPossession.setCompanyName("Company One");
- portfolio.addItemInPossession(item1InPossession);
-
- ItemEntry item1InReservation = new ItemEntry();
- item1InReservation.setIdentifier("item1");
- item1InReservation.setAmount(33);
- item1InReservation.setCompanyIdentifier("company1");
- item1InReservation.setCompanyName("Company One");
- portfolio.addReservedItem(item1InReservation);
-
- portfolio.removeReservedItem("item1", 11);
- assertEquals(22, portfolio.findReservedItemByIdentifier("item1").getAmount());
-
- portfolio.removeItemsInPossession("item1", 11);
- assertEquals(89, portfolio.findItemInPossession("item1").getAmount());
+ return item1InPossession;
}
View
77 web-ui/src/main/java/org/axonframework/samples/trader/webui/companies/CompanyController.java
@@ -96,6 +96,8 @@ public String details(@PathVariable String identifier, Model model) {
@RequestMapping(value = "/buy/{identifier}", method = RequestMethod.GET)
public String buyForm(@PathVariable String identifier, Model model) {
+ addPortfolioMoneyInfoToModel(model);
+
BuyOrder order = new BuyOrder();
prepareInitialOrder(identifier, order);
model.addAttribute("order", order);
@@ -104,6 +106,8 @@ public String buyForm(@PathVariable String identifier, Model model) {
@RequestMapping(value = "/sell/{identifier}", method = RequestMethod.GET)
public String sellForm(@PathVariable String identifier, Model model) {
+ addPortfolioItemInfoToModel(identifier, model);
+
SellOrder order = new SellOrder();
prepareInitialOrder(identifier, order);
model.addAttribute("order", order);
@@ -111,13 +115,17 @@ public String sellForm(@PathVariable String identifier, Model model) {
}
@RequestMapping(value = "/sell/{identifier}", method = RequestMethod.POST)
- public String sell(@ModelAttribute("order") @Valid SellOrder order, BindingResult bindingResult) {
+ public String sell(@ModelAttribute("order") @Valid SellOrder order, BindingResult bindingResult, Model model) {
if (!bindingResult.hasErrors()) {
- UserEntry username = userRepository.findByUsername(SecurityUtil.obtainLoggedinUsername());
+ OrderBookEntry bookEntry = obtainOrderBookForCompany(order.getCompanyId());
+ PortfolioEntry portfolioEntry = obtainPortfolioForUser();
+
+ if (portfolioEntry.obtainAmountOfAvailableItemsFor(bookEntry.getIdentifier()) < order.getTradeCount()) {
+ bindingResult.rejectValue("tradeCount", "error.order.sell.tomanyitems", "Not enough items available to create sell order.");
+ addPortfolioItemInfoToModel(order.getCompanyId(), model);
+ return "company/sell";
+ }
- // TODO: make this work for multiple orderbooks per company
- OrderBookEntry bookEntry = orderBookRepository.findByCompanyIdentifier(order.getCompanyId()).get(0);
- PortfolioEntry portfolioEntry = portfolioQueryRepository.findByUserIdentifier(username.getIdentifier());
StartSellTransactionCommand command = new StartSellTransactionCommand(
new StringAggregateIdentifier(bookEntry.getIdentifier()),
new StringAggregateIdentifier(portfolioEntry.getIdentifier()),
@@ -128,17 +136,24 @@ public String sell(@ModelAttribute("order") @Valid SellOrder order, BindingResul
return "redirect:/company/" + order.getCompanyId();
}
+
+ addPortfolioItemInfoToModel(order.getCompanyId(), model);
return "company/sell";
}
@RequestMapping(value = "/buy/{identifier}", method = RequestMethod.POST)
- public String buy(@ModelAttribute("order") @Valid BuyOrder order, BindingResult bindingResult) {
+ public String buy(@ModelAttribute("order") @Valid BuyOrder order, BindingResult bindingResult, Model model) {
if (!bindingResult.hasErrors()) {
- UserEntry username = userRepository.findByUsername(SecurityUtil.obtainLoggedinUsername());
- // TODO: make this work for multiple orderbooks per company
- OrderBookEntry bookEntry = orderBookRepository.findByCompanyIdentifier(order.getCompanyId()).get(0);
- PortfolioEntry portfolioEntry = portfolioQueryRepository.findByUserIdentifier(username.getIdentifier());
+ OrderBookEntry bookEntry = obtainOrderBookForCompany(order.getCompanyId());
+ PortfolioEntry portfolioEntry = obtainPortfolioForUser();
+
+ if (portfolioEntry.obtainMoneyToSpend() < order.getTradeCount() * order.getItemPrice()) {
+ bindingResult.rejectValue("tradeCount", "error.order.buy.notenoughmoney", "Not enough money to spend to buy the items for the price you want");
+ addPortfolioMoneyInfoToModel(portfolioEntry, model);
+ return "company/buy";
+ }
+
StartBuyTransactionCommand command = new StartBuyTransactionCommand(
new StringAggregateIdentifier(bookEntry.getIdentifier()),
new StringAggregateIdentifier(portfolioEntry.getIdentifier()),
@@ -148,9 +163,51 @@ public String buy(@ModelAttribute("order") @Valid BuyOrder order, BindingResult
return "redirect:/company/" + order.getCompanyId();
}
+ addPortfolioMoneyInfoToModel(model);
return "company/buy";
}
+ private void addPortfolioItemInfoToModel(String identifier, Model model) {
+ PortfolioEntry portfolioEntry = obtainPortfolioForUser();
+ OrderBookEntry orderBookEntry = obtainOrderBookForCompany(identifier);
+ addPortfolioItemInfoToModel(portfolioEntry, orderBookEntry.getIdentifier(), model);
+ }
+
+ private void addPortfolioItemInfoToModel(PortfolioEntry entry, String orderBookIdentifier, Model model) {
+ model.addAttribute("itemsInPossession", entry.obtainAmountOfItemsInPossessionFor(orderBookIdentifier));
+ model.addAttribute("itemsReserved", entry.obtainAmountOfReservedItemsFor(orderBookIdentifier));
+ }
+
+ private void addPortfolioMoneyInfoToModel(Model model) {
+ PortfolioEntry portfolioEntry = obtainPortfolioForUser();
+ addPortfolioMoneyInfoToModel(portfolioEntry, model);
+ }
+
+ private void addPortfolioMoneyInfoToModel(PortfolioEntry portfolioEntry, Model model) {
+ model.addAttribute("moneyInPossession", portfolioEntry.getAmountOfMoney());
+ model.addAttribute("moneyReserved", portfolioEntry.getReservedAmountOfMoney());
+ }
+
+ /**
+ * At the moment we handle the first orderBook found for a company.
+ *
+ * @param companyId Identifier for the company to obtain the orderBook for
+ * @return Found OrderBook for the company belonging to the provided identifier
+ */
+ private OrderBookEntry obtainOrderBookForCompany(String companyId) {
+ return orderBookRepository.findByCompanyIdentifier(companyId).get(0);
+ }
+
+ /**
+ * For now we work with only one portfolio per user. This might change in the future.
+ *
+ * @return The found portfolio for the logged in user.
+ */
+ private PortfolioEntry obtainPortfolioForUser() {
+ UserEntry username = userRepository.findByUsername(SecurityUtil.obtainLoggedinUsername());
+ return portfolioQueryRepository.findByUserIdentifier(username.getIdentifier());
+ }
+
private void prepareInitialOrder(String identifier, AbstractOrder order) {
CompanyEntry company = companyRepository.findOne(identifier);
order.setCompanyId(identifier);
View
8 web-ui/src/main/webapp/WEB-INF/jsp/company/buy.jsp
@@ -27,5 +27,13 @@
<li class="active">Buy</li>
</ul>
</content>
+<div class="row">
+ <div class="span14">
+ <div class="alert-message block-message info">
+ <p><c:out value="${moneyInPossession}"/> Cents available of which <c:out value="${moneyReserved}"/> cents
+ reserved.</p>
+ </div>
+ </div>
+</div>
<jsp:include page="form-include.jsp"/>
View
53 web-ui/src/main/webapp/WEB-INF/jsp/company/form-include.jsp
@@ -15,27 +15,32 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
--%>
-<form:form commandName="order">
- <form:errors path="*" cssClass="errorBox"/>
- <form:hidden path="companyId"/>
- <form:hidden path="companyName"/>
- <table>
- <tr>
- <td><spring:message code="order.price"/>:</td>
- <td><form:input path="itemPrice"/></td>
- <td><form:errors path="itemPrice" cssClass="errorBox"/></td>
- </tr>
- <tr>
- <td><spring:message code="order.tradeCount"/>:</td>
- <td><form:input path="tradeCount"/></td>
- <td><form:errors path="tradeCount" cssClass="error"/></td>
- </tr>
- <tr>
- <td colspan="3">
- <input class="btn primary" type="submit" name="submit" value="Place Order"/>
- <input class="btn" type="reset" name="reset" value="Reset"/>
- <a href="/company/<c:out value="${order.companyId}"/>" class="btn">Cancel</a>
- </td>
- </tr>
- </table>
-</form:form>
+<div class="row">
+ <div class="span14">
+
+ <form:form commandName="order">
+ <form:errors path="*" cssClass="alert-message block-message error" element="div"/>
+ <form:hidden path="companyId"/>
+ <form:hidden path="companyName"/>
+ <table>
+ <tr>
+ <td><spring:message code="order.price"/>:</td>
+ <td><form:input path="itemPrice"/></td>
+ <td><form:errors path="itemPrice" cssClass="errorBox"/></td>
+ </tr>
+ <tr>
+ <td><spring:message code="order.tradeCount"/>:</td>
+ <td><form:input path="tradeCount"/></td>
+ <td><form:errors path="tradeCount" cssClass="error"/></td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ <input class="btn primary" type="submit" name="submit" value="Place Order"/>
+ <input class="btn" type="reset" name="reset" value="Reset"/>
+ <a href="/company/<c:out value="${order.companyId}"/>" class="btn">Cancel</a>
+ </td>
+ </tr>
+ </table>
+ </form:form>
+ </div>
+</div>
View
9 web-ui/src/main/webapp/WEB-INF/jsp/company/sell.jsp
@@ -27,5 +27,12 @@
<li class="active">Sell</li>
</ul>
</content>
-
+<div class="row">
+ <div class="span14">
+ <div class="alert-message block-message info">
+ <p><c:out value="${itemsInPossession}"/> Items available of which <c:out value="${itemsReserved}"/>
+ reserved.</p>
+ </div>
+ </div>
+</div>
<jsp:include page="form-include.jsp"/>
Please sign in to comment.
Something went wrong with that request. Please try again.