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 }