001 package org.cocome.tradingsystem.systests.scenarios; 002 003 import java.util.concurrent.TimeoutException; 004 005 import org.cocome.tradingsystem.systests.interfaces.ICashBox; 006 import org.cocome.tradingsystem.systests.interfaces.ICashDesk; 007 import org.cocome.tradingsystem.systests.interfaces.IProduct; 008 import org.cocome.tradingsystem.systests.interfaces.IStorePC; 009 import org.cocome.tradingsystem.systests.util.GeneratedStockItem; 010 011 /** 012 * This abstract class holds basic operations needed for a purchase and its 013 * variants as described in use case 1. 014 * 015 * @author Benjamin Hummel 016 * @author Christian Pfaller 017 * @author $Author: hummel $ 018 * @version $Rev: 64 $ 019 * @levd.rating GREEN Rev: 64 020 */ 021 public class ProcessSaleBase extends TestScenarioBase { 022 023 /** The number of items sold for this test case. */ 024 private static final int NUM_SOLD_ITEMS = 15; 025 026 /** The number of items currently sold. */ 027 protected int currentlySold = 0; 028 029 /** The store used for this sale */ 030 protected IStorePC store; 031 032 /** The cash desk used for this sale */ 033 protected ICashDesk cashDesk; 034 035 /** The cash box used for this sale */ 036 protected ICashBox cashBox; 037 038 /** Array which holds the expected remaining amount of a product in the store */ 039 protected int[] expectedAmounts; 040 041 /** The list of products which where bought */ 042 protected IProduct[] products; 043 044 /** Holds the sum to pay */ 045 protected int priceSum; 046 047 /** Setup only a single store with two cash desks. */ 048 @Override 049 protected void setUp() throws Exception { 050 super.setUp(); 051 productGenerator.generate(100); 052 createStore(3); 053 } 054 055 /** 056 * Executes a standard purchase process at a cash desk with no exceptions. 057 * Payment will be by cash. 058 */ 059 public void purchase() throws Exception { 060 initializeCashDesk(0, 0); 061 startNewSale(); 062 enterAllRemainingProducts(); 063 064 finishSale(); 065 066 handleCashPayment(); 067 068 updateInventory(); 069 } 070 071 /** 072 * Executes actions for initializing cash desk when a customer arrives 073 * there. Corresponds to step 1 of use case 1. 074 * 075 * @param storeIndex 076 * the index of the store used. 077 * @param cashDeskIndex 078 * the index of the cash desk in the store. 079 */ 080 protected void initializeCashDesk(int storeIndex, int cashDeskIndex) 081 throws Exception { 082 // 1. The customer arrives at cash desk with goods and/or services to 083 // purchase. 084 store = stores.get(storeIndex).getStorePC(); 085 cashDesk = stores.get(storeIndex).getCashDesk(cashDeskIndex); 086 cashBox = cashDesk.getCashBox(); 087 } 088 089 /** 090 * Executes actions for starting a new sale with a default number of items. 091 * Corresponds to step 2 of use case 1. 092 */ 093 protected void startNewSale() throws Exception { 094 startNewSale(NUM_SOLD_ITEMS); 095 } 096 097 /** 098 * Executes actions for starting a new sale. Corresponds to step 2 of use 099 * case 1. 100 * 101 * @param how_many_items 102 * the number of items the sale should contain in total 103 */ 104 protected void startNewSale(int how_many_items) throws Exception { 105 // 2. The cashier starts new sale by pressing a button at the cash box. 106 cashBox.startNewSale(); 107 108 priceSum = 0; 109 currentlySold = 0; 110 expectedAmounts = new int[how_many_items]; 111 products = new IProduct[how_many_items]; 112 } 113 114 /** 115 * Executes actions for entering products in the cashbox. This is done by 116 * using the bar code scanner. Correspondes to steps 3 and 4 of use case 1. 117 * This method enters all remaining products at once. 118 */ 119 protected void enterAllRemainingProducts() throws Exception, 120 TimeoutException { 121 enterProducts(products.length - currentlySold); 122 } 123 124 /** 125 * Executes actions for entering products in the cashbox. This is done by 126 * using the bar code scanner. Correspondes to steps 3 and 4 of use case 1. 127 * 128 * @param howMany 129 * the number of products to be sold next. 130 */ 131 protected void enterProducts(int howMany) throws Exception, 132 TimeoutException { 133 for (int i = 0; i < howMany && currentlySold < products.length; ++i, ++currentlySold) { 134 // 3. The cashier enters item identifier. 135 GeneratedStockItem stockItem = stores.get(0).getStockGenerator() 136 .getGeneratedStockItem(2 * currentlySold + 3); 137 products[currentlySold] = stockItem.getProduct().getProduct(); 138 expectedAmounts[currentlySold] = stockItem.getAmount() - 1; 139 priceSum += stockItem.getSalesPrice(); 140 141 int barcode = stockItem.getProduct().getBarcode(); 142 // This can be done ... by using the barcode scanner. 143 cashDesk.getBarcodeScanner().sendBarcode(barcode); 144 145 // 4. The system records sale item and presents product description, 146 // price, and running total. 147 cashDesk.getUserDisplay().waitForUpdate(1000); 148 assertTrue(cashDesk.getUserDisplay().isPriceShown( 149 stockItem.getSalesPrice())); 150 assertTrue(cashDesk.getUserDisplay().isProductNameShown( 151 stockItem.getProduct().getName())); 152 } 153 } 154 155 /** 156 * Executes actions for finishing sale (after entering all products in 157 * cashbox, before payment). Corresponds to step 5 of use case 1. 158 */ 159 protected void finishSale() throws Exception { 160 // 5. The cashier indicates the end of entering items by pressing the 161 // SaleFinished-button at the cash box. 162 cashBox.finishSale(); 163 } 164 165 /** 166 * Executs actions of handling cash payment. Corresponds to step 5 a. of use 167 * case 1. 168 */ 169 protected void handleCashPayment() throws Exception { 170 // Holds the received payment cash 171 int payment; 172 173 // a. The cashier presses the button for bar payment. 174 cashBox.startCashPayment(); 175 176 payment = priceSum + 42; 177 // iii. The cashier enters the cash received and confirms by pressing 178 // Enter. 179 cashBox.enterReceivedCash(payment); 180 181 // i. The cash box opens. (NOTE: in the use case the cash box opens 182 // BEFORE the amount is entered. However the reference implementation 183 // expects the amount to be entered before opening the cash box, so we 184 // use this order here) 185 cashBox.waitForUpdate(1000); 186 assertTrue("The system should open the cashbox", cashBox 187 .wasOpenSignalSent()); 188 cashBox.setCashboxStatus(false); 189 190 // iv. The received money and the change amount are displayed, and the 191 // cashier hands over the change. 192 cashDesk.getUserDisplay().waitForUpdate(1000); 193 194 // v. The cashier closes the cash box. 195 cashBox.setCashboxStatus(true); 196 } 197 198 /** 199 * Executes actions after reciept of payment. Corresponds to steps 6, 7 and 200 * 8 of use case 1. 201 */ 202 protected void updateInventory() throws Exception { 203 // 6. The system logs completed sale and sends sale information to the 204 // inventory system to update the stock. 205 Thread.sleep(500); 206 for (int i = 0; i < currentlySold; ++i) { 207 assertEquals("The amount should now be as calculated", store 208 .getAmount(products[i]), expectedAmounts[i]); 209 } 210 211 // 7. The system prints the receipt and the cashier hands out the 212 // receipt. 213 cashDesk.getPrinter().waitForUpdate(500); 214 215 // 8. The customer leaves with receipt and goods. 216 } 217 218 }