001 import sale.*; 002 import sale.stdforms.*; 003 import data.*; 004 import data.ooimpl.*; 005 import data.stdforms.*; 006 import data.events.*; 007 import users.*; 008 import log.*; 009 010 import java.util.*; 011 import java.text.*; 012 import java.lang.*; 013 import java.io.*; 014 015 import javax.swing.JTextField; 016 import javax.swing.JPanel; 017 import javax.swing.JOptionPane; 018 import javax.swing.BoxLayout; 019 import javax.swing.JLabel; 020 021 022 023 /** 024 * Rückgabeprocess, der von einem registrierten Kunden 025 * am Automaten durchgeführt werden kann. 026 */ 027 public class GiveBackProcess extends SaleProcess 028 { 029 030 //// attributes //////////////////////////////////////////////////////////// 031 032 // Gates 033 protected UIGate capabilityGate; 034 protected UIGate selectionGate; 035 protected UIGate giveRestGate; 036 037 // Transitions 038 protected Transition toSelectionTransition; 039 protected Transition toGetMoneyTransition; 040 041 // verwendete Waehrung 042 protected Currency myCurrency; 043 044 // rueckzuzahlender Betrag 045 private int toPayBackValue; 046 047 // gezahlter Betrag (Verkaufspreis des Videos) 048 private IntegerValue paidValue; 049 050 // Kunde, der zurueckgeben moechte 051 private Customer customer; 052 053 // Verleihpreis eines Videos pro Tag 054 private int rentPrice = 300; 055 056 057 //// constructor /////////////////////////////////////////////////////////// 058 059 /** 060 * Erzeugt ein neues Objekt der Klasse GiveBackProcess. 061 */ 062 public GiveBackProcess() 063 { 064 super ("GiveBackProcess"); 065 } 066 067 //// protected methods ///////////////////////////////////////////////////// 068 069 /** 070 * Baut die Oberfläche für den Rückgabevorgang auf. 071 */ 072 protected void setupMachine() 073 { 074 // verwendete Waehrung ermitteln 075 myCurrency = (Currency)Shop.getTheShop().getCatalog("DM"); 076 077 // Videokatalog 078 final CatalogImpl videoCatalog = 079 (CatalogImpl)Shop.getTheShop().getCatalog("Video-Catalog"); 080 081 // zu verwendenden Datenkorb ermitteln 082 final DataBasket db = getBasket(); 083 084 085 ////////////////////////////////////////////////// 086 /// Capability-Gate ////////////////////////////// 087 ////////////////////////////////////////////////// 088 089 090 // Formsheet fuer Eingabe der Kundennummer 091 // tif ist final, damit in der anonymen Klasse des FSCC auf Attribute des tif zugegriffen werden kann 092 final TextInputForm tif = new TextInputForm("Customer-ID", 093 "Customer-ID", 094 ""); 095 096 // FormSheetContentCreator fuer Capability-Gate implementieren 097 tif.addContentCreator( 098 new FormSheetContentCreator() 099 { 100 protected void createFormSheetContent(FormSheet fs) 101 { 102 // alle vorhandenen Buttons entfernen 103 fs.removeAllButtons(); 104 105 // neuen "OK"-Button einbauen 106 fs.addButton ("Ok", 100, 107 new sale.Action() 108 { 109 public void doAction (SaleProcess p, SalesPoint sp) 110 { 111 // Eingabe ueberpruefen 112 String customerID = tif.getText(); 113 boolean isNotAnInteger = true; 114 115 try { 116 new Integer(customerID); 117 isNotAnInteger = false; 118 } 119 catch (NumberFormatException nfe) { 120 } 121 // Eingabe korrekt -> selectionGate 122 if (!isNotAnInteger && (new Integer(customerID)).intValue() > 0) 123 { 124 // existiert der Kunde? 125 try { 126 boolean customerExists = false; 127 Set customerSet = VideoMachine.getAllCustomer(); 128 Iterator i = customerSet.iterator(); 129 while (i.hasNext() && !customerExists) 130 { 131 Customer myCustomer = (Customer)i.next(); 132 if (myCustomer.getCustomerID().equals(customerID)) 133 { 134 customer = myCustomer; 135 customerExists = true; 136 } 137 } 138 139 if (customerExists) 140 { 141 capabilityGate.setNextTransition(toSelectionTransition); 142 } 143 else 144 { 145 JOptionPane.showMessageDialog(null, "This CustomerID doesn't exist!"); 146 capabilityGate.setNextTransition( 147 new GateChangeTransition(capabilityGate)); 148 } 149 } 150 catch (NullPointerException ne) { 151 JOptionPane.showMessageDialog(null, "No videos rent out!"); 152 new GateChangeTransition(capabilityGate); 153 } 154 } 155 // Eingabe falsch -> Kunden informieren und 156 // Eingabe wiederholen 157 else 158 { 159 JOptionPane.showMessageDialog(null, "CustomerID must be a positive number!"); 160 capabilityGate.setNextTransition( 161 new GateChangeTransition(capabilityGate)); 162 } 163 } 164 } 165 ); 166 167 // "Cancel"-Button einbauen 168 fs.addButton ("Cancel", 101, 169 new sale.Action() 170 { 171 public void doAction (SaleProcess p, SalesPoint sp) 172 { 173 // Transition zum Rollback-Gate als naechste Transition setzen 174 capabilityGate.setNextTransition( 175 GateChangeTransition.CHANGE_TO_ROLLBACK_GATE); 176 } 177 } 178 ); 179 } 180 } 181 ); 182 183 // Gate zur Kundennummer-Abfrage anlegen 184 capabilityGate = new UIGate((FormSheet) tif, 185 (MenuSheet) null); 186 187 188 ////////////////////////////////////////////////// 189 /// Selection-Gate /////////////////////////////// 190 ////////////////////////////////////////////////// 191 192 193 // Auswahl-Gate anlegen 194 // Das FormSheet wird durch die Transition waehrend der Laufzeit erzeugt 195 selectionGate = new UIGate((FormSheet) null, (MenuSheet) null); 196 197 // Transition zum Selection Gate 198 toSelectionTransition = 199 new Transition() 200 { 201 public Gate perform(SaleProcess pOwner, User usr) 202 { 203 // zu verwendenden Bestand ermitteln 204 StoringStock ss = customer.getStoringStock(); 205 206 // am Gate darzustellendes FormSheet 207 TwoTableFormSheet ttfs = 208 TwoTableFormSheet.create("Give Back", // Titel des FormSheets 209 ss, // Quell-StoringStock 210 db, // Ziel-DataBasket 211 selectionGate // Gate, an dem das FormSheet darzustellen ist 212 ); 213 214 // FormSheetContentCreator am Auswahl-Gate anmelden 215 ttfs.addContentCreator( 216 new FormSheetContentCreator() 217 { 218 protected void createFormSheetContent(FormSheet fs) 219 { 220 // alle vorhandenen Buttons entfernen 221 fs.removeAllButtons(); 222 223 // neuen "OK"-Button einbauen 224 fs.addButton ("Ok", 100, 225 new sale.Action() 226 { 227 public void doAction (SaleProcess p, SalesPoint sp) 228 { 229 // Transition zum Bezahlen als naechste Transition setzen 230 selectionGate.setNextTransition(toGetMoneyTransition); 231 } 232 } 233 ); 234 235 // "Cancel"-Button einbauen 236 fs.addButton ("Cancel", 101, 237 new sale.Action() 238 { 239 public void doAction (SaleProcess p, SalesPoint sp) 240 { 241 // Transition zum Rollback-Gate als naechste Transition setzen 242 selectionGate.setNextTransition( 243 GateChangeTransition.CHANGE_TO_ROLLBACK_GATE); 244 } 245 } 246 ); 247 } 248 } 249 ); 250 251 // erstelltes FormSheet am zu betretenden Gate setzen 252 selectionGate.setFormSheet(ttfs); 253 254 // als naechstes zu betretendes Gate zurueckgeben 255 return selectionGate; 256 } 257 }; 258 259 260 ////////////////////////////////////////////////// 261 /// GiveRest-Gate //////////////////////////////// 262 ////////////////////////////////////////////////// 263 264 265 // Gate zum Ausgeben des Restgeldes anlegen 266 // Das FormSheet wird durch die Transition waehrend der Laufzeit erzeugt 267 giveRestGate = new UIGate(null, null); 268 269 // Transition zum Gate, an dem das Restgeld gegeben wird 270 toGetMoneyTransition = 271 new Transition() 272 { 273 public Gate perform(SaleProcess pOwner, User usr) 274 { 275 // Parameter zum Aufsummieren des Datenkorbes festlegen 276 DataBasketCondition dbc = 277 DataBasketConditionImpl.ALL_STOCK_ITEMS; 278 int sellValue = 0; 279 int rentValue = 0; 280 281 // Videobestand des Automaten 282 CountingStockImpl videoStock = 283 (CountingStockImpl)Shop.getTheShop().getStock("Video-Countingstock"); 284 285 // aktuelle Zeit ermitteln 286 Object date = Shop.getTheShop().getTimer().getTime(); 287 288 // rueckzuzahlenden Betrag ermitteln 289 Iterator i = db.iterator(dbc); 290 291 while (i.hasNext()) 292 { 293 // spezielle Kassette ermitteln 294 StoringStockItemDBEntry cassetteItem = 295 (StoringStockItemDBEntry)i.next(); 296 CassetteStoringStockItem cassette = 297 (CassetteStoringStockItem)cassetteItem.getValue(); 298 299 // Verkaufspreis bestimmen 300 try { 301 sellValue = 302 ((NumberValue)((QuoteValue)(videoCatalog.get( 303 cassette.getName(), null, false).getValue())).getBid() 304 ).getValue().intValue(); 305 } 306 catch (VetoException ve) {} 307 308 // mind. einen Tag ausgeliehen? 309 if ((((Long)date).intValue() 310 - ((Long)cassette.getDate()).intValue()) > 0) 311 { 312 // Verleihgebuehr bestimmen 313 rentValue = (((Long)date).intValue() 314 - ((Long)cassette.getDate()).intValue()) * rentPrice; 315 316 // Leihgebuehr kleiner als Verkaufspreis? 317 if (rentValue < sellValue) 318 { 319 //rueckzuzahlenden Betrag erhoehen 320 toPayBackValue = toPayBackValue + (sellValue - rentValue); 321 322 // Video in Automatenbestand zuruecklegen 323 videoStock.add(cassette.getName(), 1, null); 324 325 // Vorgang in Logdatei eintragen 326 try { 327 Log.getGlobalLog().log(new MyLoggable(cassetteItem, 328 customer, date)); 329 } 330 catch (LogNoOutputStreamException lnose) { 331 } 332 catch (IOException ioe) { 333 } 334 } 335 // Leihgebuehr groesser als Verkaufspreis 336 else 337 { 338 JOptionPane.showMessageDialog(null, 339 cassette.getName() + " is your's!"); 340 } 341 } 342 343 // keinen Tag ausgeliehen (trotzdem 3,00 DM Leihgebuehr) 344 if ((((Long)date).intValue() 345 - ((Long)cassette.getDate()).intValue()) == 0) 346 { 347 //rueckzuzahlenden Betrag erhoehen 348 toPayBackValue = toPayBackValue + (sellValue - rentPrice); 349 350 // Video in Automatenbestand zuruecklegen 351 videoStock.add(cassette.getName(), 1, null); 352 353 // Vorgang in Logdatei eintragen 354 try { 355 Log.getGlobalLog().log(new MyLoggable(cassetteItem, 356 customer, date)); 357 } 358 catch (LogNoOutputStreamException lnose) { 359 } 360 catch (IOException ioe) { 361 } 362 } 363 } 364 365 // ueberpruefen, ob der Kunde noch Videos im Bestand hat 366 if (customer.getStoringStock().size(null) == 0) 367 VideoMachine.removeCustomer(customer); 368 369 // rueckzugebenden Betrag vom Geldbestand abziehen 370 try 371 { 372 if (toPayBackValue > 0 ) 373 { 374 ((CountingStock)Shop.getTheShop().getStock( 375 "coin slot")).remove(CurrencyImpl.PFENNIG_STCK_1, 376 toPayBackValue, pOwner.getBasket()); 377 } 378 } 379 catch (VetoException ve) { 380 } 381 382 // am Gate darzustellendes FormSheet 383 MsgForm mf = new MsgForm("Give Rest", 384 "You get " + 385 myCurrency.toString(new IntegerValue(toPayBackValue)) + 386 " back"); 387 388 // ContentCreator zur Neubelegung des "OK"-Buttons hinzufuegen 389 mf.addContentCreator( 390 new FormSheetContentCreator() 391 { 392 public void createFormSheetContent(FormSheet fs) 393 { 394 // neue Aktion setzen 395 fs.getButton(FormSheet.BTNID_OK).setAction( 396 new Action() 397 { 398 public void doAction(SaleProcess p, SalesPoint sp) 399 { 400 // zum Commit-Gate fuehrende Transition als 401 // naechste Transition setzen 402 giveRestGate.setNextTransition( 403 GateChangeTransition.CHANGE_TO_COMMIT_GATE); 404 } 405 } 406 ); 407 } 408 } 409 ); 410 411 // erstelltes FormSheet am zu betretenden Gate setzen 412 giveRestGate.setFormSheet(mf); 413 414 // als naechstes zu betretendes Gate zurueckgeben 415 return giveRestGate; 416 } 417 }; 418 } 419 420 421 //// public methods //////////////////////////////////////////////////////// 422 423 /** 424 * Gibt das Startgate des Prozesses zurück. 425 */ 426 public Gate getInitialGate() 427 { 428 // Automat aufbauen 429 setupMachine(); 430 431 // ...und Capability-Gate als Startgate zurueckgeben 432 return capabilityGate; 433 } 434 435 /** 436 * Übergibt das Log-Gate. Hier das Stop-Gate, da beim Beenden des 437 * Prozesses kein Log-Eintrag geschrieben werden soll. 438 */ 439 public Gate getLogGate() 440 { 441 return getStopGate(); 442 } 443 }