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 }